mirror of
https://github.com/Tencent/tmagic-editor.git
synced 2025-12-15 03:26:57 +08:00
Compare commits
88 Commits
v1.7.0-bet
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f7811fdb24 | ||
|
|
7a0dae9f5a | ||
|
|
304aaac8dc | ||
|
|
0f596b5c42 | ||
|
|
e3db0c93e5 | ||
|
|
3250c53097 | ||
|
|
756612eda5 | ||
|
|
2a7ab4e916 | ||
|
|
d039cee913 | ||
|
|
83664cd440 | ||
|
|
b3ce1a3b93 | ||
|
|
738e8611a4 | ||
|
|
9815fb7c51 | ||
|
|
411a28946e | ||
|
|
70d730ca82 | ||
|
|
a2a9556ab8 | ||
|
|
7e71c070f1 | ||
|
|
8d55d0cd8d | ||
|
|
8d7c8fa725 | ||
|
|
ad746319e9 | ||
|
|
0dd7f54ebc | ||
|
|
69ac90fe22 | ||
|
|
2667981e4c | ||
|
|
b536eba81c | ||
|
|
054ed561b6 | ||
|
|
c1dc58c97c | ||
|
|
bb7ec0aa1b | ||
|
|
849b4dc319 | ||
|
|
8aef360ed7 | ||
|
|
8d65127cdd | ||
|
|
93640257e9 | ||
|
|
09dfaad2cc | ||
|
|
5dbe1fb655 | ||
|
|
82df2a8f5c | ||
|
|
4dc5f0a298 | ||
|
|
3b913c1af4 | ||
|
|
310054b7d6 | ||
|
|
fa0e10f687 | ||
|
|
bf6598c871 | ||
|
|
6a7f80c48d | ||
|
|
e2708b868b | ||
|
|
97affb2bff | ||
|
|
e418130a66 | ||
|
|
55a2869818 | ||
|
|
0ecc116652 | ||
|
|
310aa47c1d | ||
|
|
27555d6b2f | ||
|
|
da9884645f | ||
|
|
1a08b16a39 | ||
|
|
a96ca8092c | ||
|
|
489d321677 | ||
|
|
3d0081e48e | ||
|
|
acda22d5cb | ||
|
|
7b19a01849 | ||
|
|
d0179028fb | ||
|
|
564a7f4271 | ||
|
|
6f0498a9e7 | ||
|
|
4f52fcb122 | ||
|
|
1297939db2 | ||
|
|
b3cfc0b5d3 | ||
|
|
b96036b23c | ||
|
|
3c3ba6525b | ||
|
|
0f3dfcf511 | ||
|
|
12e6dd18b4 | ||
|
|
cbec52936d | ||
|
|
979b834fac | ||
|
|
dabeba85a0 | ||
|
|
954bd37d52 | ||
|
|
59aa9f14b3 | ||
|
|
38192a6d48 | ||
|
|
ec479b9296 | ||
|
|
7f0aef7bee | ||
|
|
36508aba88 | ||
|
|
f30a8ddc41 | ||
|
|
a28705e3df | ||
|
|
ca0f8fc988 | ||
|
|
68c69ac405 | ||
|
|
3a9c94a6a6 | ||
|
|
5fe57cd389 | ||
|
|
51e9732894 | ||
|
|
630301bce2 | ||
|
|
507e51a2dc | ||
|
|
11d25603a8 | ||
|
|
8f0d99a4a6 | ||
|
|
08b476e04f | ||
|
|
1cb2d57ade | ||
|
|
d59428d2d6 | ||
|
|
e36da82d29 |
165
CHANGELOG.md
165
CHANGELOG.md
@ -1,3 +1,168 @@
|
|||||||
|
## [1.7.2](https://github.com/Tencent/tmagic-editor/compare/v1.7.1...v1.7.2) (2025-12-09)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.7.1](https://github.com/Tencent/tmagic-editor/compare/v1.7.0...v1.7.1) (2025-12-09)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **core:** getNode 添加stict参数来表示必须知道页面片容器id才会返回页面内的节点 ([83664cd](https://github.com/Tencent/tmagic-editor/commit/83664cd44019c3b5f05d2ad60bbb8fcf751f6b35))
|
||||||
|
* **form:** tabs组件子项配置了name后,配置生成的数据出错 ([b3ce1a3](https://github.com/Tencent/tmagic-editor/commit/b3ce1a3b930e9cbfc74b72bfb7dd9268fe341626))
|
||||||
|
* **tmagic-form:** runtime刷新导致root丢失 ([d039cee](https://github.com/Tencent/tmagic-editor/commit/d039cee9136e7e892161dafe25ff34ee95bce958))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **vue-components:** 不再兼容vue2 ([756612e](https://github.com/Tencent/tmagic-editor/commit/756612eda51fa8079420203eaca585175b039e8b))
|
||||||
|
* **vue-runtime-help:** 去掉vue2的兼容 ([2a7ab4e](https://github.com/Tencent/tmagic-editor/commit/2a7ab4e916444a68c7cc05af4fa57ddd59994393))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [1.7.0](https://github.com/Tencent/tmagic-editor/compare/v1.7.0-beta.5...v1.7.0) (2025-12-04)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **design:** dialog 默认参数 ([8d7c8fa](https://github.com/Tencent/tmagic-editor/commit/8d7c8fa725dba507c3a4874f879989ad9c050603))
|
||||||
|
* **form:** datetime如果设置为时间戳,然后初始值是一个字符串的数字显示不正确 ([7e71c07](https://github.com/Tencent/tmagic-editor/commit/7e71c070f1ee9857fd5610000188ef1a222fade1))
|
||||||
|
* **form:** table拖拽排序后重新渲染组件 ([2667981](https://github.com/Tencent/tmagic-editor/commit/2667981e4c0c451ded88e06f412dd4bcb5ec41dc))
|
||||||
|
* **form:** 生成表单values时将initValus深拷贝,避免修改到传入的对象 ([b536eba](https://github.com/Tencent/tmagic-editor/commit/b536eba81c33f8e532179b69072ea7c5d4033235))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **editor:** 代码编辑器支持配置自动高度 ([8d55d0c](https://github.com/Tencent/tmagic-editor/commit/8d55d0cd8d1059dcbca86fc5b72ec82f22c35d9c))
|
||||||
|
* **form:** table支持配置拖动操作中的按钮排序而不是拖动整行 ([69ac90f](https://github.com/Tencent/tmagic-editor/commit/69ac90fe22778fedb9e35b95595428395fd65cc5))
|
||||||
|
* **form:** table支持配置操作按钮的icon ([0dd7f54](https://github.com/Tencent/tmagic-editor/commit/0dd7f54ebc3518404653d6e43ee428e05566dd28))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [1.7.0-beta.5](https://github.com/Tencent/tmagic-editor/compare/v1.7.0-beta.4...v1.7.0-beta.5) (2025-11-24)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **element-plus-adapter:** 构建时将vue源码构建入目标代码中,导致页面存在多个版本vue ([bb7ec0a](https://github.com/Tencent/tmagic-editor/commit/bb7ec0aa1b55f83f68d7021fb98090d8e555ed65))
|
||||||
|
* **tdesign-vue-next-adapter:** 没有extra时form item不渲染help节点 ([849b4dc](https://github.com/Tencent/tmagic-editor/commit/849b4dc319b03a54dc1cfcccc1f505e61e1ccd5b))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [1.7.0-beta.4](https://github.com/Tencent/tmagic-editor/compare/v1.6.1...v1.7.0-beta.4) (2025-11-24)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **design,editro,element-plus-adapter,tdesign-vue-next-adapter:** elememt-plus表单渲染失败 ([9364025](https://github.com/Tencent/tmagic-editor/commit/93640257e90e6aa4708184a2513b80149887b0b9))
|
||||||
|
* **design:** select visible-change事件名写错 ([27555d6](https://github.com/Tencent/tmagic-editor/commit/27555d6b2f3c4c2022f77504bb4d8faf7c6f3e55))
|
||||||
|
* **editor:** 表单组件保持单向数据流 ([564a7f4](https://github.com/Tencent/tmagic-editor/commit/564a7f4271b9adb345d679f85929506e952c9cb3))
|
||||||
|
* **form:** daterange 配置names后配置失效 ([0f3dfcf](https://github.com/Tencent/tmagic-editor/commit/0f3dfcf5118e1247f351357a9eb05bfbdc7cc43b))
|
||||||
|
* **form:** dialog submit event获取到的changeRecords为空 ([cbec529](https://github.com/Tencent/tmagic-editor/commit/cbec52936db52d5c57c454468a11bea1dbbcd058))
|
||||||
|
* **form:** tabel复制行不生效 ([68c69ac](https://github.com/Tencent/tmagic-editor/commit/68c69ac4058bbe7adf00a73b21df2ec7adb713cc))
|
||||||
|
* **form:** 文本输入change出发太频繁 ([55a2869](https://github.com/Tencent/tmagic-editor/commit/55a28698183998e6dec73d8d41d5e5f029d17e7a))
|
||||||
|
* **playgournd:** 存在多个vue版本问题 ([da98846](https://github.com/Tencent/tmagic-editor/commit/da9884645fe51d3de65e461c2e434d3e221e56b5))
|
||||||
|
* **tdesign-vue-next-adapter:** select支持allowCreate ([1a08b16](https://github.com/Tencent/tmagic-editor/commit/1a08b16a399dae00e4b0d62d9d930514c84f669d))
|
||||||
|
* **vue-runtime-hlep:** 页面片销毁后需要取消app的事件监听 ([e36da82](https://github.com/Tencent/tmagic-editor/commit/e36da82d2928af6617c280939b02b6bc9f534b70))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **core:** getNode未指定页面片容器id时取获得到的第一个 ([5dbe1fb](https://github.com/Tencent/tmagic-editor/commit/5dbe1fb6555188bb17aa5b3dd1d7205b8c4d9824))
|
||||||
|
* **design, element-plus-adapter, tdesign-vue-next-adapter:** 新增popconfirm组件 ([507e51a](https://github.com/Tencent/tmagic-editor/commit/507e51a2dc91defb67087a539d786d01ef95b9ad))
|
||||||
|
* **design, element-plus-adapter, tdesign-vue-next-adapter:** 添加adapterType, 完善tdesign useZIndex ([12e6dd1](https://github.com/Tencent/tmagic-editor/commit/12e6dd18b47c4e6a11f273cbbb138c5d0e33f0ca))
|
||||||
|
* **design, form, form-schema, tdesign-vue-next-adapter:** textarea支持rows配置 ([38192a6](https://github.com/Tencent/tmagic-editor/commit/38192a6d4854904d7c1303556ad6ef4b76b7cd21))
|
||||||
|
* **design, form, tdesign-vue-next-adapter:** 完善tdesign适配 ([ca0f8fc](https://github.com/Tencent/tmagic-editor/commit/ca0f8fc9887d9fcff31052239b396d02f258d1b4))
|
||||||
|
* **design, tdesign-vue-next-adapter, table, element-plus-adapter:** 完善tdesign适配 ([979b834](https://github.com/Tencent/tmagic-editor/commit/979b834facbabf50d711b76ca5180f07b319b432))
|
||||||
|
* **design, tdesign-vue-next-adapter:** formItem新增labelAlign prop ([0ecc116](https://github.com/Tencent/tmagic-editor/commit/0ecc11665235c136a2d9e7b361fe2ecab33ff5e3))
|
||||||
|
* **design,editor,element-plus-adapter,form,table,tdesign-vue-next-adapter:** 重构table组件,适配tdesign ([08b476e](https://github.com/Tencent/tmagic-editor/commit/08b476e04f36154ef58f1f3388bc2516742e37d8))
|
||||||
|
* **design,tdesign-vue-next-adapter:** input添加click事件 ([a96ca80](https://github.com/Tencent/tmagic-editor/commit/a96ca8092c51d1700943e58e197a5d1584297d76))
|
||||||
|
* **design,tdesign-vue,next-adapter:** textarea支持autosize ([acda22d](https://github.com/Tencent/tmagic-editor/commit/acda22d5cb4905ae5d1f4bd70efb38ee5820baeb))
|
||||||
|
* **design:** 在html中添加adapter类型class ([09dfaad](https://github.com/Tencent/tmagic-editor/commit/09dfaad2ccf9cd50491a8352e33416c7a17027c4))
|
||||||
|
* **element-plus-adapter, from, tdesign-vue-adapter:** button兼容type=default和type为空的情况 ([d017902](https://github.com/Tencent/tmagic-editor/commit/d0179028fbab5b485cb0b970d8d558da4f22d869))
|
||||||
|
* **form, design, form-schema:** table支持自定义title,table 表单组件支持配置title tip ([e418130](https://github.com/Tencent/tmagic-editor/commit/e418130a66c54b7fed533977b1558e7206d729fb))
|
||||||
|
* **form:** fieldset中checkbox新增name,trueValue,falseValue配置 ([51e9732](https://github.com/Tencent/tmagic-editor/commit/51e973289473af7fae14f56e3d2fed5db838c797))
|
||||||
|
* **form:** form dialog新增props ([bf6598c](https://github.com/Tencent/tmagic-editor/commit/bf6598c8718d5f2e3d276029bf924a7de7cb458b))
|
||||||
|
* **form:** form dialog新增show close/show cancel 配置 ([310054b](https://github.com/Tencent/tmagic-editor/commit/310054b7d63e688c349142c9b7767fc5f8a2f766))
|
||||||
|
* **form:** group list新增添加按钮配置 ([3b913c1](https://github.com/Tencent/tmagic-editor/commit/3b913c1af48aa6a47e632725b008061d7faca204))
|
||||||
|
* **form:** panel点击标题可以展开或者收缩内容 ([310aa47](https://github.com/Tencent/tmagic-editor/commit/310aa47c1df9a88304f264325c697b85e09287df))
|
||||||
|
* **form:** table操作列支持配置固定在左边还是右边 ([fa0e10f](https://github.com/Tencent/tmagic-editor/commit/fa0e10f6872ade5599957051e2e6923fa2d4ca66))
|
||||||
|
* **form:** table新增新增按钮配置 ([6a7f80c](https://github.com/Tencent/tmagic-editor/commit/6a7f80c48de0e85587c27f67fe0f132f7dfee000))
|
||||||
|
* **form:** text新增prepend, append不默认使用button ([5fe57cd](https://github.com/Tencent/tmagic-editor/commit/5fe57cd389e6c955049c2ee81f62c37c7a86930f))
|
||||||
|
* **form:** text组件配置的append.hander函数添加setModel/setFormValue方法 ([6f0498a](https://github.com/Tencent/tmagic-editor/commit/6f0498a9e7ee633310b4a08374409b3f1b7607b9))
|
||||||
|
* **form:** tip图标放到label中去 ([97affb2](https://github.com/Tencent/tmagic-editor/commit/97affb2bff856b271136b50dccd45d95e17abd6a))
|
||||||
|
* **form:** 新增flex-layout组件 ([630301b](https://github.com/Tencent/tmagic-editor/commit/630301bce213e3ff28a7fb50e9cc9b8bb0c2b756))
|
||||||
|
* **form:** 新增style,fieldStyle配置;tooltip支持配置placement;配置中的函数新增getFormValue方法 ([3a9c94a](https://github.com/Tencent/tmagic-editor/commit/3a9c94a6a6529a63e022955b2f7eee23bf125d81))
|
||||||
|
* **form:** 表单校验后的错误信息将name转换成text ([ec479b9](https://github.com/Tencent/tmagic-editor/commit/ec479b9296d5dbea0df121a4702a123518808e58))
|
||||||
|
* **form:** 表格拖动支持tdesign ([e2708b8](https://github.com/Tencent/tmagic-editor/commit/e2708b868b2fbb126f1d8d846e25335b6005cd86))
|
||||||
|
* **playground:** 支持UI组件库切换 ([11d2560](https://github.com/Tencent/tmagic-editor/commit/11d25603a8b5f8bc3d9abbbeedf9c298ca0e2c72))
|
||||||
|
* **table:** action支持配置disabled ([8809351](https://github.com/Tencent/tmagic-editor/commit/88093515373e1b431c83c0da9c28a2688421d151))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [1.7.0-beta.3](https://github.com/Tencent/tmagic-editor/compare/v1.7.0-beta.2...v1.7.0-beta.3) (2025-10-31)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **editor:** 表单组件保持单向数据流 ([09663c8](https://github.com/Tencent/tmagic-editor/commit/09663c8320829dc52a4d4ffb65c73fe147a3f5fc))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **design,tdesign-vue,next-adapter:** textarea支持autosize ([be75ac9](https://github.com/Tencent/tmagic-editor/commit/be75ac994f0c03a9bdae05bc433513278d32c905))
|
||||||
|
* **element-plus-adapter, from, tdesign-vue-adapter:** button兼容type=default和type为空的情况 ([2a29971](https://github.com/Tencent/tmagic-editor/commit/2a2997131873a4836303ac2411371dd78726f6f9))
|
||||||
|
* **form:** text组件配置的append.hander函数添加setModel/setFormValue方法 ([57a634a](https://github.com/Tencent/tmagic-editor/commit/57a634a687c53132f521a8ed35a649edec488738))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [1.7.0-beta.2](https://github.com/Tencent/tmagic-editor/compare/v1.7.0-beta.1...v1.7.0-beta.2) (2025-10-28)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **form:** daterange 配置names后配置失效 ([d22e520](https://github.com/Tencent/tmagic-editor/commit/d22e520fbf6fc95c2c9600f02107d987b3a46fa7))
|
||||||
|
* **form:** dialog submit event获取到的changeRecords为空 ([02e1c7f](https://github.com/Tencent/tmagic-editor/commit/02e1c7f479e5370ba6ea2153b9547bbb0c090431))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **design, element-plus-adapter, tdesign-vue-next-adapter:** 添加adapterType, 完善tdesign useZIndex ([b312b5a](https://github.com/Tencent/tmagic-editor/commit/b312b5a5bc827a8199d5a7b36418f0ad933be081))
|
||||||
|
* **design, tdesign-vue-next-adapter, table, element-plus-adapter:** 完善tdesign适配 ([fa20837](https://github.com/Tencent/tmagic-editor/commit/fa208372ab5c204b6cb34ff977cd133156513fda))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [1.7.0-beta.1](https://github.com/Tencent/tmagic-editor/compare/v1.7.0-beta.0...v1.7.0-beta.1) (2025-10-24)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **design, form, form-schema, tdesign-vue-next-adapter:** textarea支持rows配置 ([c717472](https://github.com/Tencent/tmagic-editor/commit/c7174726b3f017afb5666f9ccc343a0c98d8d1fa))
|
||||||
|
* **form:** 表单校验后的错误信息将name转换成text ([b247490](https://github.com/Tencent/tmagic-editor/commit/b2474909cff049b0800da5be3293ad35309c1b1e))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [1.7.0-beta.0](https://github.com/Tencent/tmagic-editor/compare/v1.6.1...v1.7.0-beta.0) (2025-10-23)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **form:** tabel复制行不生效 ([6a2436f](https://github.com/Tencent/tmagic-editor/commit/6a2436fb99f15cdf662f39fd86952955fb78a9d2))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **design, element-plus-adapter, tdesign-vue-next-adapter:** 新增popconfirm组件 ([3181f32](https://github.com/Tencent/tmagic-editor/commit/3181f32b389325ca1524c42af25279ceab0a9a09))
|
||||||
|
* **design, form, tdesign-vue-next-adapter:** 完善tdesign适配 ([8ce5f71](https://github.com/Tencent/tmagic-editor/commit/8ce5f71aa26ea3fb1516aa020fa65fefdaa9cc55))
|
||||||
|
* **design,editor,element-plus-adapter,form,table,tdesign-vue-next-adapter:** 重构table组件,适配tdesign ([5b16ec0](https://github.com/Tencent/tmagic-editor/commit/5b16ec00e1de45ed50f1c206de10ad48f9d71275))
|
||||||
|
* **form:** fieldset中checkbox新增name,trueValue,falseValue配置 ([3435661](https://github.com/Tencent/tmagic-editor/commit/3435661348efce00390d0a79361073e8fea8af33))
|
||||||
|
* **form:** text新增prepend, append不默认使用button ([cea6569](https://github.com/Tencent/tmagic-editor/commit/cea65690204dbe8ccf178f92fa7c47ad6fd24a8c))
|
||||||
|
* **form:** 新增flex-layout组件 ([3e76d34](https://github.com/Tencent/tmagic-editor/commit/3e76d34f59343b5c3e833d32a35fad152a5bf7fd))
|
||||||
|
* **form:** 新增style,fieldStyle配置;tooltip支持配置placement;配置中的函数新增getFormValue方法 ([1eeabc8](https://github.com/Tencent/tmagic-editor/commit/1eeabc8220649405746558d09bd648d2b650854d))
|
||||||
|
* **playground:** 支持UI组件库切换 ([dd3e901](https://github.com/Tencent/tmagic-editor/commit/dd3e901a3d4122e6f4043521ff776fc0df478f98))
|
||||||
|
* **table:** action支持配置disabled ([8809351](https://github.com/Tencent/tmagic-editor/commit/88093515373e1b431c83c0da9c28a2688421d151))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [1.6.1](https://github.com/Tencent/tmagic-editor/compare/v1.6.0...v1.6.1) (2025-10-14)
|
## [1.6.1](https://github.com/Tencent/tmagic-editor/compare/v1.6.0...v1.6.1) (2025-10-14)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -4,34 +4,101 @@
|
|||||||
|
|
||||||
- **参数:**
|
- **参数:**
|
||||||
|
|
||||||
-
|
- {[ComponentGroup](https://github.com/Tencent/tmagic-editor/blob/5880dfbe15fcead63e9dc7c91900f8c4e7a574d8/packages/editor/src/type.ts#L355)[]} componentGroupList 组件列表配置
|
||||||
|
|
||||||
- **返回:**
|
- **返回:**
|
||||||
|
|
||||||
- `{Promise<void>}`
|
- `{void}`
|
||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
|
|
||||||
|
设置左侧面板的组件列表配置
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
该方法通常由编辑器内部调用,开发者可以通过 [m-editor 的 componentGroupList prop](./props.md#componentgrouplist) 来配置组件列表
|
||||||
|
:::
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { componentListService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
componentListService.setList([
|
||||||
|
{
|
||||||
|
title: '基础组件',
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
icon: 'text-icon',
|
||||||
|
text: '文本',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'button-icon',
|
||||||
|
text: '按钮',
|
||||||
|
type: 'button',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
## getList
|
## getList
|
||||||
|
|
||||||
- **参数:**
|
- **参数:** 无
|
||||||
|
|
||||||
-
|
|
||||||
|
|
||||||
- **返回:**
|
- **返回:**
|
||||||
|
|
||||||
- `{Promise<void>}`
|
- {[ComponentGroup](https://github.com/Tencent/tmagic-editor/blob/5880dfbe15fcead63e9dc7c91900f8c4e7a574d8/packages/editor/src/type.ts#L355)[]} 组件列表配置
|
||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
|
|
||||||
|
获取当前的组件列表配置
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { componentListService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
const list = componentListService.getList();
|
||||||
|
console.log(list);
|
||||||
|
```
|
||||||
|
|
||||||
|
## resetState
|
||||||
|
|
||||||
|
- **参数:** 无
|
||||||
|
|
||||||
|
- **返回:**
|
||||||
|
|
||||||
|
- `{void}`
|
||||||
|
|
||||||
|
- **详情:**
|
||||||
|
|
||||||
|
重置组件列表状态,清空所有配置
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { componentListService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
componentListService.resetState();
|
||||||
|
```
|
||||||
|
|
||||||
## destroy
|
## destroy
|
||||||
|
|
||||||
- **参数:**
|
- **参数:** 无
|
||||||
|
|
||||||
-
|
|
||||||
|
|
||||||
- **返回:**
|
- **返回:**
|
||||||
|
|
||||||
- `{Promise<void>}`
|
- `{void}`
|
||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
|
|
||||||
|
销毁 componentListService,清空状态并移除所有事件监听和插件
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { componentListService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
componentListService.destroy();
|
||||||
|
```
|
||||||
|
|||||||
@ -2,30 +2,540 @@
|
|||||||
|
|
||||||
## get
|
## get
|
||||||
|
|
||||||
|
- **参数:**
|
||||||
|
|
||||||
|
- `{StateKey}` name 状态键名
|
||||||
|
|
||||||
|
- **返回:**
|
||||||
|
|
||||||
|
- `{any}` 对应的状态值
|
||||||
|
|
||||||
|
- **详情:**
|
||||||
|
|
||||||
|
获取数据源服务的内部状态
|
||||||
|
|
||||||
|
可用的状态键:
|
||||||
|
- `datasourceTypeList`: 数据源类型列表
|
||||||
|
- `dataSources`: 当前数据源列表
|
||||||
|
- `editable`: 是否可编辑
|
||||||
|
- `configs`: 数据源表单配置
|
||||||
|
- `values`: 数据源默认值
|
||||||
|
- `events`: 数据源事件列表
|
||||||
|
- `methods`: 数据源方法列表
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { dataSourceService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
const dataSources = dataSourceService.get('dataSources');
|
||||||
|
console.log(dataSources);
|
||||||
|
```
|
||||||
|
|
||||||
|
## set
|
||||||
|
|
||||||
|
- **参数:**
|
||||||
|
|
||||||
|
- `{StateKey}` name 状态键名
|
||||||
|
- `{any}` value 状态值
|
||||||
|
|
||||||
|
- **返回:**
|
||||||
|
|
||||||
|
- `{void}`
|
||||||
|
|
||||||
|
- **详情:**
|
||||||
|
|
||||||
|
设置数据源服务的内部状态
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { dataSourceService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
dataSourceService.set('editable', false);
|
||||||
|
```
|
||||||
|
|
||||||
## getFormConfig
|
## getFormConfig
|
||||||
|
|
||||||
|
- **[扩展支持](../../guide/editor-expand#行为扩展):** 是
|
||||||
|
|
||||||
|
- **参数:**
|
||||||
|
|
||||||
|
- `{string}` type 数据源类型,默认为 'base'
|
||||||
|
|
||||||
|
- **返回:**
|
||||||
|
|
||||||
|
- {[FormConfig](https://github.com/Tencent/tmagic-editor/blob/c143a5f7670ae61d80c1a2cfcc780cfb5259849d/packages/form/src/schema.ts#L706)} 表单配置
|
||||||
|
|
||||||
|
- **详情:**
|
||||||
|
|
||||||
|
获取指定类型数据源的表单配置
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { dataSourceService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
const config = dataSourceService.getFormConfig('http');
|
||||||
|
console.log(config);
|
||||||
|
```
|
||||||
|
|
||||||
## setFormConfig
|
## setFormConfig
|
||||||
|
|
||||||
|
- **[扩展支持](../../guide/editor-expand#行为扩展):** 是
|
||||||
|
|
||||||
|
- **参数:**
|
||||||
|
|
||||||
|
- `{string}` type 数据源类型
|
||||||
|
- {[FormConfig](https://github.com/Tencent/tmagic-editor/blob/c143a5f7670ae61d80c1a2cfcc780cfb5259849d/packages/form/src/schema.ts#L706)} config 表单配置
|
||||||
|
|
||||||
|
- **返回:**
|
||||||
|
|
||||||
|
- `{void}`
|
||||||
|
|
||||||
|
- **详情:**
|
||||||
|
|
||||||
|
设置指定类型数据源的表单配置
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { dataSourceService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
dataSourceService.setFormConfig('http', [
|
||||||
|
{
|
||||||
|
name: 'url',
|
||||||
|
text: '请求地址',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'method',
|
||||||
|
text: '请求方法',
|
||||||
|
type: 'select',
|
||||||
|
options: [
|
||||||
|
{ text: 'GET', value: 'GET' },
|
||||||
|
{ text: 'POST', value: 'POST' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
## getFormValue
|
## getFormValue
|
||||||
|
|
||||||
|
- **[扩展支持](../../guide/editor-expand#行为扩展):** 是
|
||||||
|
|
||||||
|
- **参数:**
|
||||||
|
|
||||||
|
- `{string}` type 数据源类型,默认为 'base'
|
||||||
|
|
||||||
|
- **返回:**
|
||||||
|
|
||||||
|
- {Partial<[DataSourceSchema](https://github.com/Tencent/tmagic-editor/blob/5880dfbe15fcead63e9dc7c91900f8c4e7a574d8/packages/schema/src/index.ts#L221)>} 数据源默认值
|
||||||
|
|
||||||
|
- **详情:**
|
||||||
|
|
||||||
|
获取指定类型数据源的默认值
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { dataSourceService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
const defaultValue = dataSourceService.getFormValue('http');
|
||||||
|
console.log(defaultValue);
|
||||||
|
```
|
||||||
|
|
||||||
## setFormValue
|
## setFormValue
|
||||||
|
|
||||||
|
- **[扩展支持](../../guide/editor-expand#行为扩展):** 是
|
||||||
|
|
||||||
|
- **参数:**
|
||||||
|
|
||||||
|
- `{string}` type 数据源类型
|
||||||
|
- {Partial<[DataSourceSchema](https://github.com/Tencent/tmagic-editor/blob/5880dfbe15fcead63e9dc7c91900f8c4e7a574d8/packages/schema/src/index.ts#L221)>} value 数据源默认值
|
||||||
|
|
||||||
|
- **返回:**
|
||||||
|
|
||||||
|
- `{void}`
|
||||||
|
|
||||||
|
- **详情:**
|
||||||
|
|
||||||
|
设置指定类型数据源的默认值
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { dataSourceService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
dataSourceService.setFormValue('http', {
|
||||||
|
type: 'http',
|
||||||
|
method: 'GET',
|
||||||
|
url: '',
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
## getFormEvent
|
## getFormEvent
|
||||||
|
|
||||||
|
- **[扩展支持](../../guide/editor-expand#行为扩展):** 是
|
||||||
|
|
||||||
|
- **参数:**
|
||||||
|
|
||||||
|
- `{string}` type 数据源类型,默认为 'base'
|
||||||
|
|
||||||
|
- **返回:**
|
||||||
|
|
||||||
|
- {[EventOption](https://github.com/Tencent/tmagic-editor/blob/239b5d3efeae916a8cf3e3566d88063ecccc0553/packages/core/src/events.ts#L26-L29)[]} 事件列表
|
||||||
|
|
||||||
|
- **详情:**
|
||||||
|
|
||||||
|
获取指定类型数据源的事件列表
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { dataSourceService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
const events = dataSourceService.getFormEvent('http');
|
||||||
|
console.log(events);
|
||||||
|
```
|
||||||
|
|
||||||
## setFormEvent
|
## setFormEvent
|
||||||
|
|
||||||
|
- **[扩展支持](../../guide/editor-expand#行为扩展):** 是
|
||||||
|
|
||||||
|
- **参数:**
|
||||||
|
|
||||||
|
- `{string}` type 数据源类型
|
||||||
|
- {[EventOption](https://github.com/Tencent/tmagic-editor/blob/239b5d3efeae916a8cf3e3566d88063ecccc0553/packages/core/src/events.ts#L26-L29)[]} value 事件列表
|
||||||
|
|
||||||
|
- **返回:**
|
||||||
|
|
||||||
|
- `{void}`
|
||||||
|
|
||||||
|
- **详情:**
|
||||||
|
|
||||||
|
设置指定类型数据源的事件列表
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { dataSourceService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
dataSourceService.setFormEvent('http', [
|
||||||
|
{ label: '请求成功', value: 'success' },
|
||||||
|
{ label: '请求失败', value: 'error' },
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
## getFormMethod
|
## getFormMethod
|
||||||
|
|
||||||
|
- **[扩展支持](../../guide/editor-expand#行为扩展):** 是
|
||||||
|
|
||||||
|
- **参数:**
|
||||||
|
|
||||||
|
- `{string}` type 数据源类型,默认为 'base'
|
||||||
|
|
||||||
|
- **返回:**
|
||||||
|
|
||||||
|
- {[EventOption](https://github.com/Tencent/tmagic-editor/blob/239b5d3efeae916a8cf3e3566d88063ecccc0553/packages/core/src/events.ts#L26-L29)[]} 方法列表
|
||||||
|
|
||||||
|
- **详情:**
|
||||||
|
|
||||||
|
获取指定类型数据源的方法列表
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { dataSourceService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
const methods = dataSourceService.getFormMethod('http');
|
||||||
|
console.log(methods);
|
||||||
|
```
|
||||||
|
|
||||||
## setFormMethod
|
## setFormMethod
|
||||||
|
|
||||||
|
- **[扩展支持](../../guide/editor-expand#行为扩展):** 是
|
||||||
|
|
||||||
|
- **参数:**
|
||||||
|
|
||||||
|
- `{string}` type 数据源类型
|
||||||
|
- {[EventOption](https://github.com/Tencent/tmagic-editor/blob/239b5d3efeae916a8cf3e3566d88063ecccc0553/packages/core/src/events.ts#L26-L29)[]} value 方法列表
|
||||||
|
|
||||||
|
- **返回:**
|
||||||
|
|
||||||
|
- `{void}`
|
||||||
|
|
||||||
|
- **详情:**
|
||||||
|
|
||||||
|
设置指定类型数据源的方法列表
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { dataSourceService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
dataSourceService.setFormMethod('http', [
|
||||||
|
{ label: '发起请求', value: 'request' },
|
||||||
|
{ label: '重试', value: 'retry' },
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
## add
|
## add
|
||||||
|
|
||||||
|
- **[扩展支持](../../guide/editor-expand#行为扩展):** 是
|
||||||
|
|
||||||
|
- **参数:**
|
||||||
|
|
||||||
|
- {[DataSourceSchema](https://github.com/Tencent/tmagic-editor/blob/5880dfbe15fcead63e9dc7c91900f8c4e7a574d8/packages/schema/src/index.ts#L221)} config 数据源配置
|
||||||
|
|
||||||
|
- **返回:**
|
||||||
|
|
||||||
|
- {[DataSourceSchema](https://github.com/Tencent/tmagic-editor/blob/5880dfbe15fcead63e9dc7c91900f8c4e7a574d8/packages/schema/src/index.ts#L221)} 添加后的数据源配置
|
||||||
|
|
||||||
|
- **详情:**
|
||||||
|
|
||||||
|
添加一个数据源,如果配置中没有id或id已存在,会自动生成新的id
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { dataSourceService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
const newDs = dataSourceService.add({
|
||||||
|
type: 'http',
|
||||||
|
title: '用户信息',
|
||||||
|
url: '/api/user',
|
||||||
|
method: 'GET',
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(newDs.id); // 自动生成的id
|
||||||
|
```
|
||||||
|
|
||||||
## update
|
## update
|
||||||
|
|
||||||
|
- **[扩展支持](../../guide/editor-expand#行为扩展):** 是
|
||||||
|
|
||||||
|
- **参数:**
|
||||||
|
|
||||||
|
- {[DataSourceSchema](https://github.com/Tencent/tmagic-editor/blob/5880dfbe15fcead63e9dc7c91900f8c4e7a574d8/packages/schema/src/index.ts#L221)} config 数据源配置
|
||||||
|
- `{Object}` options 可选配置
|
||||||
|
- {[ChangeRecord](https://github.com/Tencent/tmagic-editor/blob/239b5d3efeae916a8cf3e3566d88063ecccc0553/packages/form/src/schema.ts#L27-L39)[]} changeRecords 变更记录
|
||||||
|
|
||||||
|
- **返回:**
|
||||||
|
|
||||||
|
- {[DataSourceSchema](https://github.com/Tencent/tmagic-editor/blob/5880dfbe15fcead63e9dc7c91900f8c4e7a574d8/packages/schema/src/index.ts#L221)} 更新后的数据源配置
|
||||||
|
|
||||||
|
- **详情:**
|
||||||
|
|
||||||
|
更新数据源
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { dataSourceService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
const updatedDs = dataSourceService.update({
|
||||||
|
id: 'ds_123',
|
||||||
|
type: 'http',
|
||||||
|
title: '用户详情',
|
||||||
|
url: '/api/user/detail',
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(updatedDs);
|
||||||
|
```
|
||||||
|
|
||||||
## remove
|
## remove
|
||||||
|
|
||||||
|
- **[扩展支持](../../guide/editor-expand#行为扩展):** 是
|
||||||
|
|
||||||
|
- **参数:**
|
||||||
|
|
||||||
|
- `{string}` id 数据源id
|
||||||
|
|
||||||
|
- **返回:**
|
||||||
|
|
||||||
|
- `{void}`
|
||||||
|
|
||||||
|
- **详情:**
|
||||||
|
|
||||||
|
删除指定id的数据源
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { dataSourceService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
dataSourceService.remove('ds_123');
|
||||||
|
```
|
||||||
|
|
||||||
|
## createId
|
||||||
|
|
||||||
|
- **[扩展支持](../../guide/editor-expand#行为扩展):** 是
|
||||||
|
|
||||||
|
- **参数:** 无
|
||||||
|
|
||||||
|
- **返回:**
|
||||||
|
|
||||||
|
- `{string}` 生成的唯一id
|
||||||
|
|
||||||
|
- **详情:**
|
||||||
|
|
||||||
|
生成一个唯一的数据源id,格式为 `ds_` + guid
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { dataSourceService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
const id = dataSourceService.createId();
|
||||||
|
console.log(id); // 'ds_xxx-xxx-xxx'
|
||||||
|
```
|
||||||
|
|
||||||
## getDataSourceById
|
## getDataSourceById
|
||||||
|
|
||||||
|
- **参数:**
|
||||||
|
|
||||||
|
- `{string}` id 数据源id
|
||||||
|
|
||||||
|
- **返回:**
|
||||||
|
|
||||||
|
- {[DataSourceSchema](https://github.com/Tencent/tmagic-editor/blob/5880dfbe15fcead63e9dc7c91900f8c4e7a574d8/packages/schema/src/index.ts#L221) | undefined} 数据源配置
|
||||||
|
|
||||||
|
- **详情:**
|
||||||
|
|
||||||
|
根据id获取数据源配置
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { dataSourceService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
const ds = dataSourceService.getDataSourceById('ds_123');
|
||||||
|
console.log(ds);
|
||||||
|
```
|
||||||
|
|
||||||
|
## copyWithRelated
|
||||||
|
|
||||||
|
- **参数:**
|
||||||
|
|
||||||
|
- {[MNode](https://github.com/Tencent/tmagic-editor/blob/c143a5f7670ae61d80c1a2cfcc780cfb5259849d/packages/schema/src/index.ts#L99) | [MNode](https://github.com/Tencent/tmagic-editor/blob/c143a5f7670ae61d80c1a2cfcc780cfb5259849d/packages/schema/src/index.ts#L99)[]} config 组件节点配置
|
||||||
|
- `{TargetOptions}` collectorOptions 可选的收集器配置
|
||||||
|
|
||||||
|
- **返回:**
|
||||||
|
|
||||||
|
- `{void}`
|
||||||
|
|
||||||
|
- **详情:**
|
||||||
|
|
||||||
|
复制组件时会带上组件关联的数据源,将关联的数据源存储到 localStorage
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { dataSourceService, editorService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
const node = editorService.get('node');
|
||||||
|
dataSourceService.copyWithRelated(node);
|
||||||
|
```
|
||||||
|
|
||||||
|
## paste
|
||||||
|
|
||||||
|
- **参数:** 无
|
||||||
|
|
||||||
|
- **返回:**
|
||||||
|
|
||||||
|
- `{void}`
|
||||||
|
|
||||||
|
- **详情:**
|
||||||
|
|
||||||
|
粘贴数据源,从 localStorage 中读取复制的数据源并添加到当前页面
|
||||||
|
|
||||||
|
如果数据源id已存在,则不会覆盖
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { dataSourceService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
dataSourceService.paste();
|
||||||
|
```
|
||||||
|
|
||||||
## resetState
|
## resetState
|
||||||
|
|
||||||
## destroy
|
- **参数:** 无
|
||||||
|
|
||||||
|
- **返回:**
|
||||||
|
|
||||||
|
- `{void}`
|
||||||
|
|
||||||
|
- **详情:**
|
||||||
|
|
||||||
|
重置数据源服务状态,清空所有数据源
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { dataSourceService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
dataSourceService.resetState();
|
||||||
|
```
|
||||||
|
|
||||||
|
## destroy
|
||||||
|
|
||||||
|
- **参数:** 无
|
||||||
|
|
||||||
|
- **返回:**
|
||||||
|
|
||||||
|
- `{void}`
|
||||||
|
|
||||||
|
- **详情:**
|
||||||
|
|
||||||
|
销毁 dataSourceService,移除所有事件监听并重置状态
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { dataSourceService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
dataSourceService.destroy();
|
||||||
|
```
|
||||||
|
|
||||||
|
## usePlugin
|
||||||
|
|
||||||
|
- **详情:**
|
||||||
|
|
||||||
|
相对于[use](#use), usePlugin支持更加灵活更加细致的扩展, 上述方法中标记有`扩展支持: 是`的方法都支持使用usePlugin扩展
|
||||||
|
|
||||||
|
每个支持扩展的方法都支持定制before、after两个hook来干预原有方法的行为,before可以用于修改传入参数,after可以用于修改返回的值
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { dataSourceService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
dataSourceService.usePlugin({
|
||||||
|
beforeAdd(config) {
|
||||||
|
console.log('添加前:', config);
|
||||||
|
return [config];
|
||||||
|
},
|
||||||
|
|
||||||
|
afterAdd(result, config) {
|
||||||
|
console.log('添加后:', result);
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## removeAllPlugins
|
||||||
|
|
||||||
|
- **详情:**
|
||||||
|
|
||||||
|
删掉当前设置的所有扩展
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { dataSourceService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
dataSourceService.removeAllPlugins();
|
||||||
|
```
|
||||||
@ -1,97 +1,244 @@
|
|||||||
# eventService方法
|
# eventsService方法
|
||||||
|
|
||||||
## init
|
## init
|
||||||
|
|
||||||
- **参数:**
|
- **参数:**
|
||||||
|
|
||||||
-
|
- {Record<string, { events: [EventOption](https://github.com/Tencent/tmagic-editor/blob/239b5d3efeae916a8cf3e3566d88063ecccc0553/packages/core/src/events.ts#L26-L29)[]; methods: [EventOption](https://github.com/Tencent/tmagic-editor/blob/239b5d3efeae916a8cf3e3566d88063ecccc0553/packages/core/src/events.ts#L26-L29)[] }>} eventMethodList 事件方法列表配置
|
||||||
|
|
||||||
- **返回:**
|
- **返回:**
|
||||||
|
|
||||||
- `{Promise<void>}`
|
- `{void}`
|
||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
|
|
||||||
|
初始化事件服务,设置所有组件的事件和方法列表
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
该方法通常由编辑器内部调用,开发者可以通过 [m-editor 的 eventMethodList prop](./props.md#eventmethodlist) 来配置
|
||||||
|
:::
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { eventsService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
eventsService.init({
|
||||||
|
page: {
|
||||||
|
events: [
|
||||||
|
{ label: '页面加载', value: 'load' },
|
||||||
|
{ label: '页面卸载', value: 'unload' },
|
||||||
|
],
|
||||||
|
methods: [
|
||||||
|
{ label: '刷新', value: 'refresh' },
|
||||||
|
{ label: '返回', value: 'back' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
button: {
|
||||||
|
events: [
|
||||||
|
{ label: '点击', value: 'click' },
|
||||||
|
],
|
||||||
|
methods: [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
## setEvents
|
## setEvents
|
||||||
|
|
||||||
- **参数:**
|
- **参数:**
|
||||||
|
|
||||||
-
|
- {Record<string, [EventOption](https://github.com/Tencent/tmagic-editor/blob/239b5d3efeae916a8cf3e3566d88063ecccc0553/packages/core/src/events.ts#L26-L29)[]>} events 事件配置对象
|
||||||
|
|
||||||
- **返回:**
|
- **返回:**
|
||||||
|
|
||||||
- `{Promise<void>}`
|
- `{void}`
|
||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
|
|
||||||
|
批量设置多个组件类型的事件列表
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { eventsService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
eventsService.setEvents({
|
||||||
|
page: [
|
||||||
|
{ label: '页面加载', value: 'load' },
|
||||||
|
{ label: '页面显示', value: 'show' },
|
||||||
|
],
|
||||||
|
text: [
|
||||||
|
{ label: '点击', value: 'click' },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
## setEvent
|
## setEvent
|
||||||
|
|
||||||
- **参数:**
|
- **参数:**
|
||||||
|
|
||||||
-
|
- `{string}` type 组件类型
|
||||||
|
- {[EventOption](https://github.com/Tencent/tmagic-editor/blob/239b5d3efeae916a8cf3e3566d88063ecccc0553/packages/core/src/events.ts#L26-L29)[]} events 事件列表
|
||||||
|
|
||||||
- **返回:**
|
- **返回:**
|
||||||
|
|
||||||
- `{Promise<void>}`
|
- `{void}`
|
||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
|
|
||||||
|
设置指定组件类型的事件列表
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { eventsService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
eventsService.setEvent('button', [
|
||||||
|
{ label: '点击', value: 'click' },
|
||||||
|
{ label: '长按', value: 'longpress' },
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
## getEvent
|
## getEvent
|
||||||
|
|
||||||
- **参数:**
|
- **参数:**
|
||||||
|
|
||||||
-
|
- `{string}` type 组件类型
|
||||||
|
|
||||||
- **返回:**
|
- **返回:**
|
||||||
|
|
||||||
- `{Promise<void>}`
|
- {[EventOption](https://github.com/Tencent/tmagic-editor/blob/239b5d3efeae916a8cf3e3566d88063ecccc0553/packages/core/src/events.ts#L26-L29)[]} 事件列表
|
||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
|
|
||||||
|
获取指定组件类型的事件列表
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { eventsService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
const events = eventsService.getEvent('button');
|
||||||
|
console.log(events); // [{ label: '点击', value: 'click' }, ...]
|
||||||
|
```
|
||||||
|
|
||||||
## setMethods
|
## setMethods
|
||||||
|
|
||||||
- **参数:**
|
- **参数:**
|
||||||
|
|
||||||
-
|
- {Record<string, [EventOption](https://github.com/Tencent/tmagic-editor/blob/239b5d3efeae916a8cf3e3566d88063ecccc0553/packages/core/src/events.ts#L26-L29)[]>} methods 方法配置对象
|
||||||
|
|
||||||
- **返回:**
|
- **返回:**
|
||||||
|
|
||||||
- `{Promise<void>}`
|
- `{void}`
|
||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
|
|
||||||
|
批量设置多个组件类型的方法列表
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { eventsService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
eventsService.setMethods({
|
||||||
|
page: [
|
||||||
|
{ label: '刷新', value: 'refresh' },
|
||||||
|
{ label: '滚动到顶部', value: 'scrollToTop' },
|
||||||
|
],
|
||||||
|
video: [
|
||||||
|
{ label: '播放', value: 'play' },
|
||||||
|
{ label: '暂停', value: 'pause' },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
## setMethod
|
## setMethod
|
||||||
|
|
||||||
- **参数:**
|
- **参数:**
|
||||||
|
|
||||||
-
|
- `{string}` type 组件类型
|
||||||
|
- {[EventOption](https://github.com/Tencent/tmagic-editor/blob/239b5d3efeae916a8cf3e3566d88063ecccc0553/packages/core/src/events.ts#L26-L29)[]} methods 方法列表
|
||||||
|
|
||||||
- **返回:**
|
- **返回:**
|
||||||
|
|
||||||
- `{Promise<void>}`
|
- `{void}`
|
||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
|
|
||||||
|
设置指定组件类型的方法列表
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { eventsService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
eventsService.setMethod('video', [
|
||||||
|
{ label: '播放', value: 'play' },
|
||||||
|
{ label: '暂停', value: 'pause' },
|
||||||
|
{ label: '停止', value: 'stop' },
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
## getMethod
|
## getMethod
|
||||||
|
|
||||||
- **参数:**
|
- **参数:**
|
||||||
|
|
||||||
-
|
- `{string}` type 组件类型
|
||||||
|
|
||||||
- **返回:**
|
- **返回:**
|
||||||
|
|
||||||
- `{Promise<void>}`
|
- {[EventOption](https://github.com/Tencent/tmagic-editor/blob/239b5d3efeae916a8cf3e3566d88063ecccc0553/packages/core/src/events.ts#L26-L29)[]} 方法列表
|
||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
|
|
||||||
|
获取指定组件类型的方法列表
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { eventsService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
const methods = eventsService.getMethod('video');
|
||||||
|
console.log(methods); // [{ label: '播放', value: 'play' }, ...]
|
||||||
|
```
|
||||||
|
|
||||||
|
## resetState
|
||||||
|
|
||||||
|
- **参数:** 无
|
||||||
|
|
||||||
|
- **返回:**
|
||||||
|
|
||||||
|
- `{void}`
|
||||||
|
|
||||||
|
- **详情:**
|
||||||
|
|
||||||
|
重置事件服务状态,清空所有事件和方法配置
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { eventsService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
eventsService.resetState();
|
||||||
|
```
|
||||||
|
|
||||||
## destroy
|
## destroy
|
||||||
|
|
||||||
- **参数:**
|
- **参数:** 无
|
||||||
|
|
||||||
-
|
|
||||||
|
|
||||||
- **返回:**
|
- **返回:**
|
||||||
|
|
||||||
- `{Promise<void>}`
|
- `{void}`
|
||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
|
|
||||||
|
销毁 eventsService,重置状态并移除所有事件监听和插件
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { eventsService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
eventsService.destroy();
|
||||||
|
```
|
||||||
|
|||||||
@ -967,83 +967,316 @@ const updateDragEl = (el, target) => {
|
|||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
|
|
||||||
标尺配置
|
画布标尺和参考线的配置选项
|
||||||
|
|
||||||
|
- **默认值:** `undefined`
|
||||||
|
|
||||||
- **类型:** `Partial<GuidesOptions>`
|
- **类型:** `Partial<GuidesOptions>`
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<m-editor :guides-options="guidesOptions"></m-editor>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const guidesOptions = {
|
||||||
|
// 标尺刻度单位
|
||||||
|
unit: 1,
|
||||||
|
// 标尺背景色
|
||||||
|
backgroundColor: '#f0f0f0',
|
||||||
|
// 标尺文字颜色
|
||||||
|
textColor: '#333',
|
||||||
|
// 参考线颜色
|
||||||
|
lineColor: '#ff0000',
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
## disabledPageFragment
|
## disabledPageFragment
|
||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
|
|
||||||
禁用页面片
|
禁用页面片功能
|
||||||
|
|
||||||
|
页面片是可以在多个页面中复用的组件集合
|
||||||
|
|
||||||
|
- **默认值:** `false`
|
||||||
|
|
||||||
- **类型:** `boolean`
|
- **类型:** `boolean`
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<m-editor :disabled-page-fragment="true"></m-editor>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
## disabledStageOverlay
|
## disabledStageOverlay
|
||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
|
|
||||||
禁用双击在浮层中单独编辑选中组件
|
禁用双击在浮层中单独编辑选中组件的功能
|
||||||
|
|
||||||
|
启用时,双击组件可以在浮层中单独编辑,避免其他组件干扰
|
||||||
|
|
||||||
|
- **默认值:** `false`
|
||||||
|
|
||||||
- **类型:** `boolean`
|
- **类型:** `boolean`
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<m-editor :disabled-stage-overlay="true"></m-editor>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
## disabledShowSrc
|
## disabledShowSrc
|
||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
|
|
||||||
禁用属性配置面板右下角显示源码的按钮
|
禁用属性配置面板右下角"显示源码"的按钮
|
||||||
|
|
||||||
|
该按钮可以查看和编辑组件的 JSON 配置
|
||||||
|
|
||||||
|
- **默认值:** `false`
|
||||||
|
|
||||||
- **类型:** `boolean`
|
- **类型:** `boolean`
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<m-editor :disabled-show-src="true"></m-editor>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
## disabledDataSource
|
## disabledDataSource
|
||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
|
|
||||||
禁用数据源
|
禁用数据源功能
|
||||||
|
|
||||||
|
禁用后,左侧面板将不显示数据源选项卡
|
||||||
|
|
||||||
|
- **默认值:** `false`
|
||||||
|
|
||||||
- **类型:** `boolean`
|
- **类型:** `boolean`
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<m-editor :disabled-data-source="true"></m-editor>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
## disabledCodeBlock
|
## disabledCodeBlock
|
||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
|
|
||||||
禁用代码块
|
禁用代码块功能
|
||||||
|
|
||||||
|
禁用后,左侧面板将不显示代码块选项卡
|
||||||
|
|
||||||
|
- **默认值:** `false`
|
||||||
|
|
||||||
- **类型:** `boolean`
|
- **类型:** `boolean`
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<m-editor :disabled-code-block="true"></m-editor>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
## treeIndent
|
## treeIndent
|
||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
|
|
||||||
已选组件、代码编辑、数据源缩进配置
|
组件树、代码块列表、数据源列表的缩进配置(单位:px)
|
||||||
|
|
||||||
|
- **默认值:** `undefined`
|
||||||
|
|
||||||
- **类型:** `number`
|
- **类型:** `number`
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<m-editor :tree-indent="20"></m-editor>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
## treeNextLevelIndentIncrement
|
## treeNextLevelIndentIncrement
|
||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
|
|
||||||
已选组件、代码编辑、数据源子节点缩进增量配置
|
组件树、代码块列表、数据源列表子节点缩进增量配置(单位:px)
|
||||||
|
|
||||||
|
每一级子节点会在父节点缩进基础上增加该值
|
||||||
|
|
||||||
|
- **默认值:** `undefined`
|
||||||
|
|
||||||
- **类型:** `number`
|
- **类型:** `number`
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<!-- 第一级缩进20px,第二级缩进35px,第三级缩进50px -->
|
||||||
|
<m-editor :tree-indent="20" :tree-next-level-indent-increment="15"></m-editor>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
## customContentMenu
|
## customContentMenu
|
||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
|
|
||||||
用于自定义组件树与画布的右键菜单
|
用于自定义组件树与画布的右键菜单
|
||||||
|
|
||||||
- **类型:** `function`
|
该函数会在显示右键菜单前被调用,接收默认菜单项作为参数,返回最终显示的菜单项
|
||||||
|
|
||||||
|
- **默认值:** `(menus) => menus`
|
||||||
|
|
||||||
|
- **类型:** `(menus: (MenuButton | MenuComponent)[], data: { node?: MNode; page?: MPage; parent?: MContainer; stage?: StageCore }) => (MenuButton | MenuComponent)[]`
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<m-editor :custom-content-menu="customContentMenu"></m-editor>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const customContentMenu = (menus, { node }) => {
|
||||||
|
// 为特定类型的组件添加自定义菜单
|
||||||
|
if (node?.type === 'container') {
|
||||||
|
menus.push({
|
||||||
|
type: 'button',
|
||||||
|
text: '清空容器',
|
||||||
|
handler: () => {
|
||||||
|
// 清空容器的逻辑
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 可以过滤掉某些菜单项
|
||||||
|
return menus.filter(menu => menu.text !== '删除');
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
## extendFormState
|
||||||
|
|
||||||
|
- **详情:**
|
||||||
|
|
||||||
|
扩展表单状态
|
||||||
|
|
||||||
|
用于在属性表单中注入自定义的状态数据,这些数据可以在表单配置的各个字段为函数时的第一个参数中获取
|
||||||
|
|
||||||
|
- **默认值:** `undefined`
|
||||||
|
|
||||||
|
- **类型:** `(state: FormState) => Record<string, any> | Promise<Record<string, any>>`
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<m-editor :extend-form-state="extendFormState"></m-editor>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const extendFormState = async (state) => {
|
||||||
|
// 返回自定义的状态数据
|
||||||
|
return {
|
||||||
|
// 可以是同步数据
|
||||||
|
currentUser: {
|
||||||
|
name: 'Admin',
|
||||||
|
role: 'admin',
|
||||||
|
},
|
||||||
|
// 也可以是异步获取的数据
|
||||||
|
projectConfig: await fetchProjectConfig(),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
扩展的状态可以在表单配置中通过 `state` 访问,例如:
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
name: 'title',
|
||||||
|
text: '标题',
|
||||||
|
// 根据扩展的状态动态设置
|
||||||
|
disabled: (state) => state.currentUser.role !== 'admin',
|
||||||
|
}
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
## pageBarSortOptions
|
## pageBarSortOptions
|
||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
|
|
||||||
页面顺序拖拽配置参数
|
页面标签栏的拖拽排序配置参数
|
||||||
|
|
||||||
|
用于配置页面标签的拖拽排序行为
|
||||||
|
|
||||||
|
- **默认值:** `undefined`
|
||||||
|
|
||||||
|
- **类型:** [PageBarSortOptions](https://github.com/Tencent/tmagic-editor/blob/master/packages/editor/src/type.ts)
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<m-editor :page-bar-sort-options="sortOptions"></m-editor>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const sortOptions = {
|
||||||
|
// 是否启用拖拽排序
|
||||||
|
animation: 150,
|
||||||
|
// 拖拽手柄的class
|
||||||
|
handle: '.page-bar-item',
|
||||||
|
// 其他 sortablejs 配置
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
## pageFilterFunction
|
## pageFilterFunction
|
||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
|
|
||||||
页面搜索函数
|
页面搜索/过滤函数
|
||||||
|
|
||||||
|
用于自定义页面的搜索逻辑,在页面列表中输入关键词时会调用该函数进行过滤
|
||||||
|
|
||||||
|
- **默认值:** `undefined`
|
||||||
|
|
||||||
|
- **类型:** `(page: MPage | MPageFragment, keyword: string) => boolean`
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<m-editor :page-filter-function="pageFilterFunction"></m-editor>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const pageFilterFunction = (page, keyword) => {
|
||||||
|
// 自定义搜索逻辑
|
||||||
|
// 不仅搜索页面名称,还搜索页面的其他属性
|
||||||
|
return (
|
||||||
|
page.name?.includes(keyword) ||
|
||||||
|
page.title?.includes(keyword) ||
|
||||||
|
page.id?.includes(keyword)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|||||||
@ -1,29 +1,111 @@
|
|||||||
# Editor组件 slots
|
# Editor组件 slots
|
||||||
|
|
||||||
|
## header
|
||||||
|
|
||||||
|
- **详情:** 编辑器最顶部区域
|
||||||
|
|
||||||
|
- **默认:** 无
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<m-editor>
|
||||||
|
<template #header>
|
||||||
|
<div class="custom-header">自定义头部内容</div>
|
||||||
|
</template>
|
||||||
|
</m-editor>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
## nav
|
## nav
|
||||||
|
|
||||||
- **详情:** 编辑器顶部菜单栏
|
- **详情:** 编辑器顶部菜单栏
|
||||||
|
|
||||||
- **默认:** [NavMenu.vue](https://github.com/Tencent/tmagic-editor/blob/239b5d3efeae916a8cf3e3566d88063ecccc0553/packages/editor/src/layouts/NavMenu.vue)
|
- **默认:** [NavMenu.vue](https://github.com/Tencent/tmagic-editor/blob/239b5d3efeae916a8cf3e3566d88063ecccc0553/packages/editor/src/layouts/NavMenu.vue)
|
||||||
|
|
||||||
|
- **插槽 Props:**
|
||||||
|
- `editorService`: editorService 实例
|
||||||
|
|
||||||
:::warning
|
:::warning
|
||||||
属性配置[menu](./props.md#menu)由默认组件接收,如设置该slot,[menu](./props.md#menu)配置将失效
|
属性配置[menu](./props.md#menu)由默认组件接收,如设置该slot,[menu](./props.md#menu)配置将失效
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<m-editor>
|
||||||
|
<template #nav="{ editorService }">
|
||||||
|
<div class="custom-nav">
|
||||||
|
<button @click="save">保存</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</m-editor>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
## content-before
|
||||||
|
|
||||||
|
- **详情:** 编辑器主要内容区域之前
|
||||||
|
|
||||||
|
- **默认:** 无
|
||||||
|
|
||||||
|
## src-code
|
||||||
|
|
||||||
|
- **详情:** 源码查看区域
|
||||||
|
|
||||||
|
- **默认:** 默认的代码编辑器
|
||||||
|
|
||||||
|
- **插槽 Props:**
|
||||||
|
- `editorService`: editorService 实例
|
||||||
|
|
||||||
## sidebar
|
## sidebar
|
||||||
|
|
||||||
- **详情:** 左边栏
|
- **详情:** 左边栏
|
||||||
|
|
||||||
- **默认:** [Sidebar.vue](https://github.com/Tencent/tmagic-editor/blob/239b5d3efeae916a8cf3e3566d88063ecccc0553/packages/editor/src/layouts/sidebar/Sidebar.vue)
|
- **默认:** [Sidebar.vue](https://github.com/Tencent/tmagic-editor/blob/239b5d3efeae916a8cf3e3566d88063ecccc0553/packages/editor/src/layouts/sidebar/Sidebar.vue)
|
||||||
|
|
||||||
|
- **插槽 Props:**
|
||||||
|
- `editorService`: editorService 实例
|
||||||
|
|
||||||
:::warning
|
:::warning
|
||||||
属性配置[sidebar](./props.md#sidebar)由默认组件接收,如设置该slot,[sidebar](./props.md#sidebar)配置将失效
|
属性配置[sidebar](./props.md#sidebar)由默认组件接收,如设置该slot,[sidebar](./props.md#sidebar)配置将失效
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<m-editor>
|
||||||
|
<template #sidebar="{ editorService }">
|
||||||
|
<div class="custom-sidebar">
|
||||||
|
<!-- 自定义侧边栏内容 -->
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</m-editor>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
## component-list
|
||||||
|
|
||||||
|
- **详情:** 左边栏中的组件列表
|
||||||
|
|
||||||
|
- **默认:** 默认的组件列表
|
||||||
|
|
||||||
|
- **插槽 Props:**
|
||||||
|
- `componentGroupList`: 组件分组列表
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
如设置了[sidebar](#sidebar)插槽,此插槽将失效
|
||||||
|
:::
|
||||||
|
|
||||||
## component-list-panel-header
|
## component-list-panel-header
|
||||||
|
|
||||||
- **详情:** 左边栏中的组件列表内上方位置
|
- **详情:** 左边栏中的组件列表内上方位置
|
||||||
|
|
||||||
|
- **默认:** 无
|
||||||
|
|
||||||
:::warning
|
:::warning
|
||||||
如设置了[sidebar](#sidebar)插槽,此插槽将失效
|
如设置了[sidebar](#sidebar)插槽,此插槽将失效
|
||||||
:::
|
:::
|
||||||
@ -34,24 +116,84 @@
|
|||||||
|
|
||||||
- **默认:** 图片加文案
|
- **默认:** 图片加文案
|
||||||
|
|
||||||
|
- **插槽 Props:**
|
||||||
|
- `component`: 组件配置对象
|
||||||
|
|
||||||
:::warning
|
:::warning
|
||||||
如设置了[sidebar](#sidebar)插槽,此插槽将失效
|
如设置了[sidebar](#sidebar)插槽,此插槽将失效
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<m-editor>
|
||||||
|
<template #component-list-item="{ component }">
|
||||||
|
<div class="custom-item">
|
||||||
|
<span>{{ component.text }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</m-editor>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
## layer-panel-header
|
## layer-panel-header
|
||||||
|
|
||||||
- **详情:** 左边栏中的已选组件(组件树)内顶部位置
|
- **详情:** 左边栏中的已选组件(组件树)内顶部位置
|
||||||
|
|
||||||
|
- **默认:** 无
|
||||||
|
|
||||||
:::warning
|
:::warning
|
||||||
如设置了[sidebar](#sidebar)插槽,此插槽将失效
|
如设置了[sidebar](#sidebar)插槽,此插槽将失效
|
||||||
:::
|
:::
|
||||||
|
|
||||||
## layer-node-content
|
## layer-node-content
|
||||||
|
|
||||||
- **详情:** 左边栏中的已选组件(组件树)节点
|
- **详情:** 左边栏中的已选组件(组件树)节点完整内容
|
||||||
|
|
||||||
|
- **默认:** 组件名称加id和工具按钮
|
||||||
|
|
||||||
|
- **插槽 Props:**
|
||||||
|
- `data`: 节点数据
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
如设置了[sidebar](#sidebar)插槽,此插槽将失效
|
||||||
|
:::
|
||||||
|
|
||||||
|
## layer-node-label
|
||||||
|
|
||||||
|
- **详情:** 左边栏中的已选组件(组件树)节点标签部分
|
||||||
|
|
||||||
- **默认:** 组件名称加id
|
- **默认:** 组件名称加id
|
||||||
|
|
||||||
|
- **插槽 Props:**
|
||||||
|
- `data`: 节点数据
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
如设置了[sidebar](#sidebar)插槽,此插槽将失效
|
||||||
|
:::
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<m-editor>
|
||||||
|
<template #layer-node-label="{ data }">
|
||||||
|
<span>{{ data.type }} - {{ data.name }}</span>
|
||||||
|
</template>
|
||||||
|
</m-editor>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
## layer-node-tool
|
||||||
|
|
||||||
|
- **详情:** 左边栏中的已选组件(组件树)节点右侧工具区域
|
||||||
|
|
||||||
|
- **默认:** 无
|
||||||
|
|
||||||
|
- **插槽 Props:**
|
||||||
|
- `data`: 节点数据
|
||||||
|
|
||||||
:::warning
|
:::warning
|
||||||
如设置了[sidebar](#sidebar)插槽,此插槽将失效
|
如设置了[sidebar](#sidebar)插槽,此插槽将失效
|
||||||
:::
|
:::
|
||||||
@ -60,6 +202,8 @@
|
|||||||
|
|
||||||
- **详情:** 左边栏中的代码块列表内顶部位置
|
- **详情:** 左边栏中的代码块列表内顶部位置
|
||||||
|
|
||||||
|
- **默认:** 无
|
||||||
|
|
||||||
:::warning
|
:::warning
|
||||||
如设置了[sidebar](#sidebar)插槽,此插槽将失效
|
如设置了[sidebar](#sidebar)插槽,此插槽将失效
|
||||||
:::
|
:::
|
||||||
@ -68,13 +212,44 @@
|
|||||||
|
|
||||||
- **详情:** 左边栏中的代码块列表中代码块右侧位置
|
- **详情:** 左边栏中的代码块列表中代码块右侧位置
|
||||||
|
|
||||||
|
- **默认:** 无
|
||||||
|
|
||||||
|
- **插槽 Props:**
|
||||||
|
- `id`: 代码块id
|
||||||
|
- `data`: 代码块数据
|
||||||
|
|
||||||
:::warning
|
:::warning
|
||||||
如设置了[sidebar](#sidebar)插槽,此插槽将失效
|
如设置了[sidebar](#sidebar)插槽,此插槽将失效
|
||||||
:::
|
:::
|
||||||
|
|
||||||
## code-block-edit-panel-header
|
## code-block-panel-search
|
||||||
|
|
||||||
- **详情:** 代码块弹窗编辑器中弹窗顶部区域
|
- **详情:** 左边栏中的代码块列表搜索框位置
|
||||||
|
|
||||||
|
- **默认:** 无
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
如设置了[sidebar](#sidebar)插槽,此插槽将失效
|
||||||
|
:::
|
||||||
|
|
||||||
|
## data-source-panel-tool
|
||||||
|
|
||||||
|
- **详情:** 左边栏中的数据源列表中数据源右侧位置
|
||||||
|
|
||||||
|
- **默认:** 无
|
||||||
|
|
||||||
|
- **插槽 Props:**
|
||||||
|
- `data`: 数据源数据
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
如设置了[sidebar](#sidebar)插槽,此插槽将失效
|
||||||
|
:::
|
||||||
|
|
||||||
|
## data-source-panel-search
|
||||||
|
|
||||||
|
- **详情:** 左边栏中的数据源列表搜索框位置
|
||||||
|
|
||||||
|
- **默认:** 无
|
||||||
|
|
||||||
:::warning
|
:::warning
|
||||||
如设置了[sidebar](#sidebar)插槽,此插槽将失效
|
如设置了[sidebar](#sidebar)插槽,此插槽将失效
|
||||||
@ -86,6 +261,9 @@
|
|||||||
|
|
||||||
- **默认:** [Workspace.vue](https://github.com/Tencent/tmagic-editor/blob/239b5d3efeae916a8cf3e3566d88063ecccc0553/packages/editor/src/layouts/workspace/Workspace.vue)
|
- **默认:** [Workspace.vue](https://github.com/Tencent/tmagic-editor/blob/239b5d3efeae916a8cf3e3566d88063ecccc0553/packages/editor/src/layouts/workspace/Workspace.vue)
|
||||||
|
|
||||||
|
- **插槽 Props:**
|
||||||
|
- `editorService`: editorService 实例
|
||||||
|
|
||||||
## stage
|
## stage
|
||||||
|
|
||||||
- **详情:** 画布
|
- **详情:** 画布
|
||||||
@ -94,15 +272,63 @@
|
|||||||
|
|
||||||
## workspace-content
|
## workspace-content
|
||||||
|
|
||||||
- **详情:** 编辑器中间区域内
|
- **详情:** 编辑器中间区域内,画布上方位置
|
||||||
|
|
||||||
|
- **默认:** 无
|
||||||
|
|
||||||
|
- **插槽 Props:**
|
||||||
|
- `editorService`: editorService 实例
|
||||||
|
|
||||||
|
## page-bar
|
||||||
|
|
||||||
|
- **详情:** 编辑器中间区域底部页面标签栏
|
||||||
|
|
||||||
|
- **默认:** 默认的页面标签栏
|
||||||
|
|
||||||
|
## page-bar-add-button
|
||||||
|
|
||||||
|
- **详情:** 页面标签栏中的"添加页面"按钮
|
||||||
|
|
||||||
|
- **默认:** 默认的添加按钮
|
||||||
|
|
||||||
## page-bar-title
|
## page-bar-title
|
||||||
|
|
||||||
- **详情:** 编辑器中间区域底部页面标题
|
- **详情:** 编辑器中间区域底部页面标题
|
||||||
|
|
||||||
|
- **默认:** 页面名称
|
||||||
|
|
||||||
|
- **插槽 Props:**
|
||||||
|
- `page`: 页面配置对象
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<m-editor>
|
||||||
|
<template #page-bar-title="{ page }">
|
||||||
|
<span>{{ page.name }} - {{ page.id }}</span>
|
||||||
|
</template>
|
||||||
|
</m-editor>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
## page-bar-popover
|
## page-bar-popover
|
||||||
|
|
||||||
- **详情:** 编辑器中间区域底部页面标题悬浮框
|
- **详情:** 编辑器中间区域底部页面标题悬浮框内容
|
||||||
|
|
||||||
|
- **默认:** 页面详细信息
|
||||||
|
|
||||||
|
- **插槽 Props:**
|
||||||
|
- `page`: 页面配置对象
|
||||||
|
|
||||||
|
## page-list-popover
|
||||||
|
|
||||||
|
- **详情:** 页面列表弹出框内容
|
||||||
|
|
||||||
|
- **默认:** 页面列表
|
||||||
|
|
||||||
|
- **插槽 Props:**
|
||||||
|
- `list`: 页面列表
|
||||||
|
|
||||||
## props-panel
|
## props-panel
|
||||||
|
|
||||||
@ -114,8 +340,40 @@
|
|||||||
|
|
||||||
- **详情:** 编辑器右侧属性配置内顶部区域
|
- **详情:** 编辑器右侧属性配置内顶部区域
|
||||||
|
|
||||||
|
- **默认:** 无
|
||||||
|
|
||||||
|
## content-after
|
||||||
|
|
||||||
|
- **详情:** 编辑器主要内容区域之后
|
||||||
|
|
||||||
|
- **默认:** 无
|
||||||
|
|
||||||
|
## footer
|
||||||
|
|
||||||
|
- **详情:** 编辑器底部区域
|
||||||
|
|
||||||
|
- **默认:** 无
|
||||||
|
|
||||||
## empty
|
## empty
|
||||||
|
|
||||||
- **详情:** 当前没有页面时,编辑器中间区域
|
- **详情:** 当前没有页面时,编辑器中间区域
|
||||||
|
|
||||||
- **默认:** [AddPageBox.vue](https://github.com/Tencent/tmagic-editor/blob/239b5d3efeae916a8cf3e3566d88063ecccc0553/packages/editor/src/layouts/AddPageBox.vue)
|
- **默认:** [AddPageBox.vue](https://github.com/Tencent/tmagic-editor/blob/239b5d3efeae916a8cf3e3566d88063ecccc0553/packages/editor/src/layouts/AddPageBox.vue)
|
||||||
|
|
||||||
|
- **插槽 Props:**
|
||||||
|
- `editorService`: editorService 实例
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<m-editor>
|
||||||
|
<template #empty="{ editorService }">
|
||||||
|
<div class="custom-empty">
|
||||||
|
<p>暂无页面</p>
|
||||||
|
<button @click="createFirstPage">创建第一个页面</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</m-editor>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|||||||
@ -4,114 +4,250 @@
|
|||||||
|
|
||||||
- **[扩展支持](../../guide/editor-expand#行为扩展):** 是
|
- **[扩展支持](../../guide/editor-expand#行为扩展):** 是
|
||||||
|
|
||||||
- **参数:**
|
- **参数:** 无
|
||||||
|
|
||||||
-
|
|
||||||
|
|
||||||
- **返回:**
|
- **返回:**
|
||||||
|
|
||||||
- `{Promise<void>}`
|
- `{Storage}` Storage 对象
|
||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
|
|
||||||
|
获取数据存储对象,默认返回 localStorage
|
||||||
|
|
||||||
|
可以通过插件机制替换为其他存储对象(如 sessionStorage)
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { storageService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
const storage = storageService.getStorage();
|
||||||
|
console.log(storage); // localStorage
|
||||||
|
|
||||||
|
// 通过插件替换为 sessionStorage
|
||||||
|
storageService.usePlugin({
|
||||||
|
afterGetStorage() {
|
||||||
|
return window.sessionStorage;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
## getNamespace
|
## getNamespace
|
||||||
|
|
||||||
- **[扩展支持](../../guide/editor-expand#行为扩展):** 是
|
- **[扩展支持](../../guide/editor-expand#行为扩展):** 是
|
||||||
|
|
||||||
- **参数:**
|
- **参数:** 无
|
||||||
|
|
||||||
-
|
|
||||||
|
|
||||||
- **返回:**
|
- **返回:**
|
||||||
|
|
||||||
- `{Promise<void>}`
|
- `{string}` 命名空间字符串
|
||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
|
|
||||||
|
获取存储项的命名空间,默认为 'tmagic'
|
||||||
|
|
||||||
|
命名空间用于区分不同应用的存储数据
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { storageService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
const namespace = storageService.getNamespace();
|
||||||
|
console.log(namespace); // 'tmagic'
|
||||||
|
```
|
||||||
|
|
||||||
## clear
|
## clear
|
||||||
|
|
||||||
- **[扩展支持](../../guide/editor-expand#行为扩展):** 是
|
- **[扩展支持](../../guide/editor-expand#行为扩展):** 是
|
||||||
|
|
||||||
- **参数:**
|
- **参数:** 无
|
||||||
|
|
||||||
-
|
|
||||||
|
|
||||||
- **返回:**
|
- **返回:**
|
||||||
|
|
||||||
- `{Promise<void>}`
|
- `{void}`
|
||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
|
|
||||||
|
清空当前存储对象中的所有数据
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { storageService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
storageService.clear();
|
||||||
|
```
|
||||||
|
|
||||||
## getItem
|
## getItem
|
||||||
|
|
||||||
- **[扩展支持](../../guide/editor-expand#行为扩展):** 是
|
- **[扩展支持](../../guide/editor-expand#行为扩展):** 是
|
||||||
|
|
||||||
- **参数:**
|
- **参数:**
|
||||||
|
|
||||||
-
|
- `{string}` key 存储项的键名
|
||||||
|
- `{Options}` options 可选配置
|
||||||
|
- `namespace?: string` 自定义命名空间
|
||||||
|
- `protocol?: Protocol` 数据协议类型
|
||||||
|
|
||||||
- **返回:**
|
- **返回:**
|
||||||
|
|
||||||
- `{Promise<void>}`
|
- `{any}` 存储的值,如果不存在返回 null
|
||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
|
|
||||||
|
获取存储项,支持多种数据类型的自动解析
|
||||||
|
|
||||||
|
支持的协议类型:
|
||||||
|
- `Protocol.OBJECT`: JavaScript 对象
|
||||||
|
- `Protocol.JSON`: JSON 格式
|
||||||
|
- `Protocol.NUMBER`: 数字类型
|
||||||
|
- `Protocol.BOOLEAN`: 布尔类型
|
||||||
|
- `Protocol.STRING`: 字符串类型
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { storageService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
// 获取字符串
|
||||||
|
const str = storageService.getItem('myKey');
|
||||||
|
|
||||||
|
// 使用自定义命名空间
|
||||||
|
const value = storageService.getItem('key', { namespace: 'custom' });
|
||||||
|
|
||||||
|
// 指定协议类型
|
||||||
|
const num = storageService.getItem('count', { protocol: Protocol.NUMBER });
|
||||||
|
```
|
||||||
|
|
||||||
## key
|
## key
|
||||||
|
|
||||||
- **参数:**
|
- **参数:**
|
||||||
|
|
||||||
-
|
- `{number}` index 索引位置
|
||||||
|
|
||||||
- **返回:**
|
- **返回:**
|
||||||
|
|
||||||
- `{Promise<void>}`
|
- `{string | null}` 指定位置的键名,不存在返回 null
|
||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
|
|
||||||
|
获取存储对象中指定索引位置的键名
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { storageService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
const firstKey = storageService.key(0);
|
||||||
|
console.log(firstKey);
|
||||||
|
```
|
||||||
|
|
||||||
## removeItem
|
## removeItem
|
||||||
|
|
||||||
- **[扩展支持](../../guide/editor-expand#行为扩展):** 是
|
- **[扩展支持](../../guide/editor-expand#行为扩展):** 是
|
||||||
|
|
||||||
- **参数:**
|
- **参数:**
|
||||||
|
|
||||||
-
|
- `{string}` key 存储项的键名
|
||||||
|
- `{Options}` options 可选配置
|
||||||
|
- `namespace?: string` 自定义命名空间
|
||||||
|
|
||||||
- **返回:**
|
- **返回:**
|
||||||
|
|
||||||
- `{Promise<void>}`
|
- `{void}`
|
||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
|
|
||||||
|
移除指定的存储项
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { storageService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
// 移除默认命名空间下的存储项
|
||||||
|
storageService.removeItem('myKey');
|
||||||
|
|
||||||
|
// 移除自定义命名空间下的存储项
|
||||||
|
storageService.removeItem('key', { namespace: 'custom' });
|
||||||
|
```
|
||||||
|
|
||||||
## setItem
|
## setItem
|
||||||
|
|
||||||
- **[扩展支持](../../guide/editor-expand#行为扩展):** 是
|
- **[扩展支持](../../guide/editor-expand#行为扩展):** 是
|
||||||
|
|
||||||
- **参数:**
|
- **参数:**
|
||||||
|
|
||||||
-
|
- `{string}` key 存储项的键名
|
||||||
|
- `{any}` value 要存储的值
|
||||||
|
- `{Options}` options 可选配置
|
||||||
|
- `namespace?: string` 自定义命名空间
|
||||||
|
- `protocol?: Protocol` 数据协议类型
|
||||||
|
|
||||||
- **返回:**
|
- **返回:**
|
||||||
|
|
||||||
- `{Promise<void>}`
|
- `{void}`
|
||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
|
|
||||||
|
设置存储项,自动序列化复杂数据类型
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { storageService, Protocol } from '@tmagic/editor';
|
||||||
|
|
||||||
|
// 存储字符串
|
||||||
|
storageService.setItem('name', 'tmagic');
|
||||||
|
|
||||||
|
// 存储对象
|
||||||
|
storageService.setItem('config', { a: 1, b: 2 }, { protocol: Protocol.OBJECT });
|
||||||
|
|
||||||
|
// 存储数字
|
||||||
|
storageService.setItem('count', 100, { protocol: Protocol.NUMBER });
|
||||||
|
|
||||||
|
// 使用自定义命名空间
|
||||||
|
storageService.setItem('key', 'value', { namespace: 'custom' });
|
||||||
|
```
|
||||||
|
|
||||||
## destroy
|
## destroy
|
||||||
|
|
||||||
- **参数:**
|
- **参数:** 无
|
||||||
|
|
||||||
-
|
|
||||||
|
|
||||||
- **返回:**
|
- **返回:**
|
||||||
|
|
||||||
- `{Promise<void>}`
|
- `{void}`
|
||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
|
|
||||||
|
销毁 storageService,移除所有事件监听和插件
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { storageService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
storageService.destroy();
|
||||||
|
```
|
||||||
|
|
||||||
## use
|
## use
|
||||||
|
|
||||||
使用中间件的方式扩展方法,上述方法中标记有`扩展支持: 是`的方法都支持使用use扩展
|
使用中间件的方式扩展方法,上述方法中标记有`扩展支持: 是`的方法都支持使用use扩展
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { storageService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
storageService.use({
|
||||||
|
getItem(key, options, next) {
|
||||||
|
console.log('获取存储项:', key);
|
||||||
|
return next();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
## usePlugin
|
## usePlugin
|
||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
@ -120,9 +256,35 @@
|
|||||||
|
|
||||||
每个支持扩展的方法都支持定制before、after两个hook来干预原有方法的行为,before可以用于修改传入参数,after可以用于修改返回的值
|
每个支持扩展的方法都支持定制before、after两个hook来干预原有方法的行为,before可以用于修改传入参数,after可以用于修改返回的值
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { storageService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
storageService.usePlugin({
|
||||||
|
beforeSetItem(key, value, options) {
|
||||||
|
console.log('设置前:', key, value);
|
||||||
|
return [key, value, options];
|
||||||
|
},
|
||||||
|
|
||||||
|
afterGetItem(result, key, options) {
|
||||||
|
console.log('获取后:', result);
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
## removeAllPlugins
|
## removeAllPlugins
|
||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
|
|
||||||
删掉当前设置的所有扩展
|
删掉当前设置的所有扩展
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { storageService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
storageService.removeAllPlugins();
|
||||||
|
```
|
||||||
|
|
||||||
|
|||||||
@ -1,12 +1,89 @@
|
|||||||
# uiService方法
|
# uiService方法
|
||||||
|
|
||||||
|
## set
|
||||||
|
|
||||||
|
- **参数:**
|
||||||
|
|
||||||
|
- `{keyof UiState}` name 状态键名
|
||||||
|
- `{any}` value 状态值
|
||||||
|
|
||||||
|
- **返回:**
|
||||||
|
|
||||||
|
- `{void}`
|
||||||
|
|
||||||
|
- **详情:**
|
||||||
|
|
||||||
|
设置UI服务的状态
|
||||||
|
|
||||||
|
可用的状态键:
|
||||||
|
- `uiSelectMode`: UI选择模式
|
||||||
|
- `showSrc`: 是否显示源码
|
||||||
|
- `showStylePanel`: 是否显示样式面板
|
||||||
|
- `zoom`: 缩放比例
|
||||||
|
- `stageContainerRect`: 画布容器尺寸
|
||||||
|
- `stageRect`: 画布尺寸
|
||||||
|
- `columnWidth`: 列宽度配置
|
||||||
|
- `showGuides`: 是否显示参考线
|
||||||
|
- `showRule`: 是否显示标尺
|
||||||
|
- `propsPanelSize`: 属性面板尺寸
|
||||||
|
- `showAddPageButton`: 是否显示添加页面按钮
|
||||||
|
- `showPageListButton`: 是否显示页面列表按钮
|
||||||
|
- `hideSlideBar`: 是否隐藏侧边栏
|
||||||
|
- `sideBarItems`: 侧边栏项目
|
||||||
|
- `navMenuRect`: 导航菜单尺寸
|
||||||
|
- `frameworkRect`: 框架尺寸
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { uiService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
// 设置缩放比例
|
||||||
|
uiService.set('zoom', 1.5);
|
||||||
|
|
||||||
|
// 设置画布尺寸
|
||||||
|
uiService.set('stageRect', { width: 375, height: 667 });
|
||||||
|
|
||||||
|
// 显示/隐藏参考线
|
||||||
|
uiService.set('showGuides', true);
|
||||||
|
|
||||||
|
// 显示/隐藏标尺
|
||||||
|
uiService.set('showRule', true);
|
||||||
|
```
|
||||||
|
|
||||||
|
## get
|
||||||
|
|
||||||
|
- **参数:**
|
||||||
|
|
||||||
|
- `{keyof UiState}` name 状态键名
|
||||||
|
|
||||||
|
- **返回:**
|
||||||
|
|
||||||
|
- `{any}` 对应的状态值
|
||||||
|
|
||||||
|
- **详情:**
|
||||||
|
|
||||||
|
获取UI服务的状态值
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { uiService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
const zoom = uiService.get('zoom');
|
||||||
|
console.log('当前缩放:', zoom);
|
||||||
|
|
||||||
|
const stageRect = uiService.get('stageRect');
|
||||||
|
console.log('画布尺寸:', stageRect);
|
||||||
|
```
|
||||||
|
|
||||||
## zoom
|
## zoom
|
||||||
|
|
||||||
- **[扩展支持](../../guide/editor-expand#行为扩展):** 是
|
- **[扩展支持](../../guide/editor-expand#行为扩展):** 是
|
||||||
|
|
||||||
- **参数:**
|
- **参数:**
|
||||||
|
|
||||||
- `{number}` zoom 缩放倍数
|
- `{number}` zoom 缩放增量(可以为负数)
|
||||||
|
|
||||||
- **返回:**
|
- **返回:**
|
||||||
|
|
||||||
@ -14,24 +91,111 @@
|
|||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
|
|
||||||
设置缩放倍数,最小为0.1
|
调整缩放倍数,最小为0.1
|
||||||
|
|
||||||
|
传入的值会被累加到当前缩放倍数上
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { uiService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
// 放大0.1倍
|
||||||
|
await uiService.zoom(0.1);
|
||||||
|
|
||||||
|
// 缩小0.1倍
|
||||||
|
await uiService.zoom(-0.1);
|
||||||
|
|
||||||
|
// 当前缩放如果是1.0,执行zoom(0.5)后变为1.5
|
||||||
|
await uiService.zoom(0.5);
|
||||||
|
```
|
||||||
|
|
||||||
## calcZoom
|
## calcZoom
|
||||||
|
|
||||||
- **[扩展支持](../../guide/editor-expand#行为扩展):** 是
|
- **[扩展支持](../../guide/editor-expand#行为扩展):** 是
|
||||||
|
|
||||||
|
- **参数:** 无
|
||||||
|
|
||||||
- **返回:**
|
- **返回:**
|
||||||
|
|
||||||
- `{Promise<number>}`
|
- `{Promise<number>}` 计算出的缩放倍数
|
||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
|
|
||||||
计算出缩放以适应的倍数
|
计算"缩放以适应"的倍数
|
||||||
|
|
||||||
|
根据画布容器的尺寸和画布尺寸自动计算出合适的缩放比例,使画布完全显示在容器内
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { uiService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
const fitZoom = await uiService.calcZoom();
|
||||||
|
console.log('适应缩放:', fitZoom);
|
||||||
|
|
||||||
|
// 应用缩放以适应
|
||||||
|
uiService.set('zoom', fitZoom);
|
||||||
|
```
|
||||||
|
|
||||||
|
## resetState
|
||||||
|
|
||||||
|
- **参数:** 无
|
||||||
|
|
||||||
|
- **返回:**
|
||||||
|
|
||||||
|
- `{void}`
|
||||||
|
|
||||||
|
- **详情:**
|
||||||
|
|
||||||
|
重置UI服务状态到初始值
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { uiService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
uiService.resetState();
|
||||||
|
```
|
||||||
|
|
||||||
|
## destroy
|
||||||
|
|
||||||
|
- **参数:** 无
|
||||||
|
|
||||||
|
- **返回:**
|
||||||
|
|
||||||
|
- `{void}`
|
||||||
|
|
||||||
|
- **详情:**
|
||||||
|
|
||||||
|
销毁 uiService,重置状态并移除所有事件监听和插件
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { uiService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
uiService.destroy();
|
||||||
|
```
|
||||||
|
|
||||||
## use
|
## use
|
||||||
|
|
||||||
使用中间件的方式扩展方法,上述方法中标记有`扩展支持: 是`的方法都支持使用use扩展
|
使用中间件的方式扩展方法,上述方法中标记有`扩展支持: 是`的方法都支持使用use扩展
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { uiService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
uiService.use({
|
||||||
|
async zoom(value, next) {
|
||||||
|
console.log('缩放前:', uiService.get('zoom'));
|
||||||
|
await next();
|
||||||
|
console.log('缩放后:', uiService.get('zoom'));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
## usePlugin
|
## usePlugin
|
||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
@ -40,9 +204,36 @@
|
|||||||
|
|
||||||
每个支持扩展的方法都支持定制before、after两个hook来干预原有方法的行为,before可以用于修改传入参数,after可以用于修改返回的值
|
每个支持扩展的方法都支持定制before、after两个hook来干预原有方法的行为,before可以用于修改传入参数,after可以用于修改返回的值
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { uiService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
uiService.usePlugin({
|
||||||
|
beforeZoom(value) {
|
||||||
|
console.log('缩放增量:', value);
|
||||||
|
return [value];
|
||||||
|
},
|
||||||
|
|
||||||
|
afterCalcZoom(result) {
|
||||||
|
console.log('计算的缩放:', result);
|
||||||
|
// 可以修改返回值
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
## removeAllPlugins
|
## removeAllPlugins
|
||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
|
|
||||||
删掉当前设置的所有扩展
|
删掉当前设置的所有扩展
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { uiService } from '@tmagic/editor';
|
||||||
|
|
||||||
|
uiService.removeAllPlugins();
|
||||||
|
```
|
||||||
|
|
||||||
|
|||||||
@ -2,14 +2,109 @@
|
|||||||
|
|
||||||
## sort-change
|
## sort-change
|
||||||
|
|
||||||
|
- **参数:**
|
||||||
|
- `{ column, prop, order }` - 排序信息对象
|
||||||
|
- `column: Object` - 排序的列配置
|
||||||
|
- `prop: string` - 排序的列属性名
|
||||||
|
- `order: 'ascending' | 'descending' | null` - 排序方式
|
||||||
|
|
||||||
|
- **说明:** 当表格的排序条件发生变化时触发
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
```js
|
||||||
|
const handleSortChange = ({ column, prop, order }) => {
|
||||||
|
console.log('排序变化:', prop, order);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
## after-action
|
## after-action
|
||||||
|
|
||||||
|
- **参数:**
|
||||||
|
- `action: string` - 操作类型
|
||||||
|
- `data: any` - 操作相关数据
|
||||||
|
|
||||||
|
- **说明:** 表格操作完成后触发
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
```js
|
||||||
|
const handleAfterAction = (action, data) => {
|
||||||
|
console.log('操作完成:', action, data);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
## select
|
## select
|
||||||
|
|
||||||
|
- **参数:**
|
||||||
|
- `selection: Array<any>` - 当前选中的行数据数组
|
||||||
|
- `row: any` - 刚刚被选中的行数据
|
||||||
|
|
||||||
|
- **说明:** 当用户手动勾选某一行时触发
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
```js
|
||||||
|
const handleSelect = (selection, row) => {
|
||||||
|
console.log('选中行:', row);
|
||||||
|
console.log('当前选中:', selection);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
## select-all
|
## select-all
|
||||||
|
|
||||||
|
- **参数:**
|
||||||
|
- `selection: Array<any>` - 当前选中的行数据数组
|
||||||
|
|
||||||
|
- **说明:** 当用户手动勾选全选 Checkbox 时触发
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
```js
|
||||||
|
const handleSelectAll = (selection) => {
|
||||||
|
console.log('全选/取消全选:', selection.length);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
## selection-change
|
## selection-change
|
||||||
|
|
||||||
|
- **参数:**
|
||||||
|
- `selection: Array<any>` - 当前选中的行数据数组
|
||||||
|
|
||||||
|
- **说明:** 当选择项发生变化时触发
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
```js
|
||||||
|
const handleSelectionChange = (selection) => {
|
||||||
|
console.log('选中项变化:', selection);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
## expand-change
|
## expand-change
|
||||||
|
|
||||||
|
- **参数:**
|
||||||
|
- `row: any` - 被展开/收起的行数据
|
||||||
|
- `expandedRows: Array<any>` - 当前所有展开的行数据数组
|
||||||
|
|
||||||
|
- **说明:** 当用户展开或收起某一行时触发(用于可展开表格)
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
```js
|
||||||
|
const handleExpandChange = (row, expandedRows) => {
|
||||||
|
console.log('展开状态变化:', row);
|
||||||
|
console.log('当前展开行:', expandedRows);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
## cell-click
|
## cell-click
|
||||||
|
|
||||||
|
- **参数:**
|
||||||
|
- `row: any` - 行数据
|
||||||
|
- `column: Object` - 列配置
|
||||||
|
- `cell: HTMLElement` - 单元格 DOM 元素
|
||||||
|
- `event: Event` - 原生事件对象
|
||||||
|
|
||||||
|
- **说明:** 当某个单元格被点击时触发
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
```js
|
||||||
|
const handleCellClick = (row, column, cell, event) => {
|
||||||
|
console.log('单元格点击:', row, column.property);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|||||||
@ -2,6 +2,40 @@
|
|||||||
|
|
||||||
## toggleRowSelection
|
## toggleRowSelection
|
||||||
|
|
||||||
|
- **参数:**
|
||||||
|
- `row: any` - 要切换选中状态的行数据
|
||||||
|
- `selected?: boolean` - 是否选中,不传则切换当前状态
|
||||||
|
|
||||||
|
- **说明:** 切换某一行的选中状态
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
```js
|
||||||
|
tableRef.value.toggleRowSelection(row, true); // 选中
|
||||||
|
tableRef.value.toggleRowSelection(row, false); // 取消选中
|
||||||
|
tableRef.value.toggleRowSelection(row); // 切换状态
|
||||||
|
```
|
||||||
|
|
||||||
## toggleRowExpansion
|
## toggleRowExpansion
|
||||||
|
|
||||||
|
- **参数:**
|
||||||
|
- `row: any` - 要展开/收起的行数据
|
||||||
|
- `expanded?: boolean` - 是否展开,不传则切换当前状态
|
||||||
|
|
||||||
|
- **说明:** 切换某一行的展开状态(用于可展开表格)
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
```js
|
||||||
|
tableRef.value.toggleRowExpansion(row, true); // 展开
|
||||||
|
tableRef.value.toggleRowExpansion(row, false); // 收起
|
||||||
|
```
|
||||||
|
|
||||||
## clearSelection
|
## clearSelection
|
||||||
|
|
||||||
|
- **参数:** 无
|
||||||
|
|
||||||
|
- **说明:** 清空所有选中的行
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
```js
|
||||||
|
tableRef.value.clearSelection();
|
||||||
|
```
|
||||||
|
|||||||
@ -2,123 +2,122 @@
|
|||||||
|
|
||||||
## data
|
## data
|
||||||
|
|
||||||
- **详情:**
|
- **详情:** 表格数据,数组格式
|
||||||
|
|
||||||
|
|
||||||
|
- **默认值:** `[]`
|
||||||
|
|
||||||
- **默认值:**
|
- **类型:** `Array<any>`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- **类型:**
|
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
```js
|
||||||
|
[
|
||||||
|
{ id: 1, name: '张三', age: 20 },
|
||||||
|
{ id: 2, name: '李四', age: 25 }
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
## columns
|
## columns
|
||||||
|
|
||||||
- **详情:**
|
- **详情:** 表格列配置
|
||||||
|
|
||||||
|
|
||||||
|
- **默认值:** `[]`
|
||||||
|
|
||||||
- **默认值:**
|
- **类型:** `Array<ColumnConfig>`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- **类型:**
|
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
|
```js
|
||||||
|
[
|
||||||
|
{ prop: 'name', label: '姓名', width: 120 },
|
||||||
|
{ prop: 'age', label: '年龄', width: 80 }
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
## spanMethod
|
## spanMethod
|
||||||
|
|
||||||
- **详情:** 合并行或列的计算方法
|
- **详情:** 合并行或列的计算方法
|
||||||
|
|
||||||
|
- **默认值:** `undefined`
|
||||||
|
|
||||||
|
- **类型:** `Function`
|
||||||
|
|
||||||
|
- **参数:**
|
||||||
|
- `{ row, column, rowIndex, columnIndex }`
|
||||||
|
|
||||||
|
- **返回值:** `[rowspan, colspan]` 或 `{ rowspan, colspan }`
|
||||||
|
|
||||||
- **默认值:**
|
- **示例:**
|
||||||
|
```js
|
||||||
|
({ rowIndex, columnIndex }) => {
|
||||||
|
if (rowIndex % 2 === 0) {
|
||||||
- **类型:**
|
if (columnIndex === 0) {
|
||||||
|
return [1, 2];
|
||||||
|
} else if (columnIndex === 1) {
|
||||||
|
return [0, 0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## loading
|
## loading
|
||||||
|
|
||||||
- **详情:**
|
- **详情:** 是否显示加载状态
|
||||||
|
|
||||||
|
|
||||||
|
- **默认值:** `false`
|
||||||
|
|
||||||
- **默认值:**
|
- **类型:** `boolean`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- **类型:**
|
|
||||||
|
|
||||||
|
|
||||||
## showHeader
|
## showHeader
|
||||||
|
|
||||||
- **详情:** 是否显示表头
|
- **详情:** 是否显示表头
|
||||||
|
|
||||||
|
- **默认值:** `true`
|
||||||
|
|
||||||
- **默认值:**
|
- **类型:** `boolean`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- **类型:**
|
|
||||||
|
|
||||||
## bodyHeight
|
## bodyHeight
|
||||||
|
|
||||||
- **详情:** Table的最大高度。合法的值为数字或者单位为 px 的高度
|
- **详情:** Table 的最大高度。合法的值为数字或者单位为 px 的高度
|
||||||
|
|
||||||
- **默认值:**
|
- **默认值:** `undefined`
|
||||||
|
|
||||||
|
- **类型:** `string | number`
|
||||||
|
|
||||||
|
- **示例:**
|
||||||
- **类型:**
|
```js
|
||||||
|
bodyHeight: 400
|
||||||
|
bodyHeight: '400px'
|
||||||
|
```
|
||||||
|
|
||||||
## emptyText
|
## emptyText
|
||||||
|
|
||||||
- **详情:** 空数据时显示的文本内容
|
- **详情:** 空数据时显示的文本内容
|
||||||
|
|
||||||
- **默认值:**
|
- **默认值:** `'暂无数据'`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- **类型:**
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- **类型:** `string`
|
||||||
|
|
||||||
## defaultExpandAll
|
## defaultExpandAll
|
||||||
|
|
||||||
- **详情:** 是否默认展开所有行,当Table包含展开行存在或者为树形表格时有效
|
- **详情:** 是否默认展开所有行,当 Table 包含展开行存在或者为树形表格时有效
|
||||||
|
|
||||||
- **默认值:**
|
- **默认值:** `false`
|
||||||
|
|
||||||
|
|
||||||
- **类型:**
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- **类型:** `boolean`
|
||||||
|
|
||||||
## rowkeyName
|
## rowkeyName
|
||||||
|
|
||||||
- **详情:**
|
- **详情:** 行数据的 Key,用来优化 Table 的渲染
|
||||||
|
|
||||||
|
|
||||||
|
- **默认值:** `'id'`
|
||||||
|
|
||||||
- **默认值:**
|
- **类型:** `string`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- **类型:**
|
|
||||||
|
|
||||||
|
- **说明:** 在使用 reserve-selection 功能与显示树形数据时,该属性是必填的
|
||||||
|
|
||||||
## border
|
## border
|
||||||
|
|
||||||
- **详情:**
|
- **详情:** 是否显示边框
|
||||||
|
|
||||||
|
|
||||||
|
- **默认值:** `false`
|
||||||
|
|
||||||
- **默认值:**
|
- **类型:** `boolean`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- **类型:**
|
|
||||||
|
|
||||||
|
|||||||
@ -62,6 +62,59 @@ MenuButton 的[定义](https://github.com/Tencent/tmagic-editor/blob/239b5d3efea
|
|||||||
|
|
||||||
### 二、左侧菜单栏
|
### 二、左侧菜单栏
|
||||||
|
|
||||||
|
左侧菜单栏主要展示组件列表、组件树、代码块、数据源等内容。可以通过 `m-editor` 组件的 [sidebar](/api/editor/props.html#sidebar) `prop` 来进行配置。
|
||||||
|
|
||||||
|
#### 1. 自定义左侧面板
|
||||||
|
|
||||||
|
可以使用 `sidebar` slot 来完全自定义左侧面板:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<m-editor>
|
||||||
|
<template #sidebar>
|
||||||
|
<your-sidebar></your-sidebar>
|
||||||
|
</template>
|
||||||
|
</m-editor>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. 扩展组件列表
|
||||||
|
|
||||||
|
通过 [componentGroupList](/api/editor/props.html#componentgrouplist) prop 配置组件分组和列表:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const componentGroupList = [
|
||||||
|
{
|
||||||
|
title: '基础组件',
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
text: '文本',
|
||||||
|
type: 'text',
|
||||||
|
icon: 'text-icon'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '按钮',
|
||||||
|
type: 'button',
|
||||||
|
icon: 'button-icon'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '业务组件',
|
||||||
|
items: [
|
||||||
|
// 自定义业务组件
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. 组件树扩展
|
||||||
|
|
||||||
|
组件树会自动根据页面配置生成,可以通过 `editorService` 监听组件树相关事件:
|
||||||
|
|
||||||
|
```js
|
||||||
|
editorService.on('select', (node) => {
|
||||||
|
console.log('选中组件:', node);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
### 三、右侧属性配置栏
|
### 三、右侧属性配置栏
|
||||||
|
|
||||||
@ -118,6 +171,50 @@ propsService.usePlugin({
|
|||||||
</m-editor>
|
</m-editor>
|
||||||
```
|
```
|
||||||
|
|
||||||
### 四、中间工作区域
|
|
||||||
|
|
||||||
## 行为扩展
|
## 行为扩展
|
||||||
|
|
||||||
|
### 二、服务扩展
|
||||||
|
|
||||||
|
可以通过监听事件和使用插件来扩展 EditorService:
|
||||||
|
|
||||||
|
```js
|
||||||
|
// 监听编辑器事件
|
||||||
|
editorService.on('add', (node) => {
|
||||||
|
console.log('添加组件:', node);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 使用插件扩展
|
||||||
|
editorService.usePlugin({
|
||||||
|
beforeAdd(node) {
|
||||||
|
// 在添加组件前执行
|
||||||
|
return node;
|
||||||
|
},
|
||||||
|
afterAdd(node) {
|
||||||
|
// 在添加组件后执行
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. PropsService 扩展
|
||||||
|
|
||||||
|
自定义属性配置的处理逻辑:
|
||||||
|
|
||||||
|
```js
|
||||||
|
propsService.usePlugin({
|
||||||
|
// 修改属性配置
|
||||||
|
beforeGetPropsConfig(type) {
|
||||||
|
console.log('获取配置前:', type);
|
||||||
|
},
|
||||||
|
|
||||||
|
afterGetPropsConfig(config, type) {
|
||||||
|
// 添加自定义配置
|
||||||
|
return config;
|
||||||
|
},
|
||||||
|
|
||||||
|
// 自定义配置填充逻辑
|
||||||
|
afterFillConfig(config, type) {
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|||||||
37
package.json
37
package.json
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.6.1",
|
"version": "1.7.2",
|
||||||
"name": "tmagic",
|
"name": "tmagic",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@ -40,43 +40,44 @@
|
|||||||
"url": "https://github.com/Tencent/tmagic-editor.git"
|
"url": "https://github.com/Tencent/tmagic-editor.git"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@commitlint/cli": "^19.8.1",
|
"@commitlint/cli": "^20.1.0",
|
||||||
"@commitlint/config-conventional": "^19.8.1",
|
"@commitlint/config-conventional": "^20.0.0",
|
||||||
"@rollup/plugin-alias": "^5.1.1",
|
"@rollup/plugin-alias": "^6.0.0",
|
||||||
"@tmagic/eslint-config": "workspace:*",
|
"@tmagic/eslint-config": "workspace:*",
|
||||||
"@types/node": "24.0.10",
|
"@types/node": "24.0.10",
|
||||||
"@vitejs/plugin-vue": "^5.2.3",
|
"@vitejs/plugin-vue": "^6.0.2",
|
||||||
"@vitest/coverage-v8": "^2.1.9",
|
"@vitest/coverage-v8": "^4.0.12",
|
||||||
"@vue/compiler-sfc": "catalog:",
|
"@vue/compiler-sfc": "catalog:",
|
||||||
"c8": "^7.14.0",
|
"c8": "^10.1.3",
|
||||||
"commitizen": "^4.3.1",
|
"commitizen": "^4.3.1",
|
||||||
"conventional-changelog-cli": "^5.0.0",
|
"conventional-changelog-cli": "^5.0.0",
|
||||||
"cosmiconfig": "^8.3.6",
|
"cosmiconfig": "^ 9.0.0 ",
|
||||||
"cz-conventional-changelog": "^3.3.0",
|
"cz-conventional-changelog": "^3.3.0",
|
||||||
"element-plus": "^2.11.4",
|
"element-plus": "^2.11.8",
|
||||||
"enquirer": "^2.4.1",
|
"enquirer": "^2.4.1",
|
||||||
"eslint": "^9.37.0",
|
"eslint": "^9.39.1",
|
||||||
"execa": "^4.1.0",
|
"execa": "^9.6.0",
|
||||||
"highlight.js": "^11.11.1",
|
"highlight.js": "^11.11.1",
|
||||||
"husky": "^9.1.7",
|
"husky": "^9.1.7",
|
||||||
"jsdom": "^19.0.0",
|
"jsdom": "^27.2.0",
|
||||||
"lint-staged": "^16.1.0",
|
"lint-staged": "^16.2.7",
|
||||||
"minimist": "^1.2.8",
|
"minimist": "^1.2.8",
|
||||||
"picocolors": "^1.1.1",
|
"picocolors": "^1.1.1",
|
||||||
"prettier": "^3.6.2",
|
"prettier": "^3.6.2",
|
||||||
"recast": "^0.23.11",
|
"recast": "^0.23.11",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"rollup": "4.44.1",
|
"rollup": "4.44.1",
|
||||||
"rollup-plugin-dts": "^6.2.1",
|
"rollup-plugin-dts": "^6.2.3",
|
||||||
"semver": "^7.7.1",
|
"sass-embedded": "^1.93.3",
|
||||||
"serialize-javascript": "^6.0.2",
|
"semver": "^7.7.3",
|
||||||
|
"serialize-javascript": "^7.0.0",
|
||||||
"shx": "^0.3.4",
|
"shx": "^0.3.4",
|
||||||
"typescript": "catalog:",
|
"typescript": "catalog:",
|
||||||
"vite": "catalog:",
|
"vite": "catalog:",
|
||||||
"vitepress": "^1.6.4",
|
"vitepress": "^1.6.4",
|
||||||
"vitest": "^3.2.4",
|
"vitest": "^4.0.12",
|
||||||
"vue": "catalog:",
|
"vue": "catalog:",
|
||||||
"vue-tsc": "^3.1.1"
|
"vue-tsc": "^3.1.4"
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"commitizen": {
|
"commitizen": {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.6.1",
|
"version": "1.7.2",
|
||||||
"name": "@tmagic/cli",
|
"name": "@tmagic/cli",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"types": "lib/index.d.ts",
|
"types": "lib/index.d.ts",
|
||||||
|
|||||||
@ -2,8 +2,9 @@ import path from 'node:path';
|
|||||||
|
|
||||||
import fs from 'fs-extra';
|
import fs from 'fs-extra';
|
||||||
|
|
||||||
|
import { prepareEntryFile } from './utils/prepareEntryFile';
|
||||||
|
import { resolveAppPackages } from './utils/resolveAppPackages';
|
||||||
import { ModuleMainFilePath, UserConfig } from './types';
|
import { ModuleMainFilePath, UserConfig } from './types';
|
||||||
import { prepareEntryFile, resolveAppPackages } from './utils';
|
|
||||||
|
|
||||||
export default class Core {
|
export default class Core {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.6.1",
|
"version": "1.7.2",
|
||||||
"name": "@tmagic/core",
|
"name": "@tmagic/core",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "dist/tmagic-core.umd.cjs",
|
"main": "dist/tmagic-core.umd.cjs",
|
||||||
|
|||||||
@ -279,13 +279,13 @@ export default class EventHelper extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const toNodes = [];
|
const toNodes = [];
|
||||||
const toNode = this.app.getNode(to);
|
const toNode = this.app.getNode(to, { strict: true });
|
||||||
if (toNode) {
|
if (toNode) {
|
||||||
toNodes.push(toNode);
|
toNodes.push(toNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const [, page] of this.app.pageFragments) {
|
for (const [, page] of this.app.pageFragments) {
|
||||||
const node = page.getNode(to);
|
const node = page.getNode(to, { strict: true });
|
||||||
if (node) {
|
if (node) {
|
||||||
toNodes.push(node);
|
toNodes.push(node);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -191,7 +191,7 @@ class Node extends EventEmitter {
|
|||||||
if (this.app.eventHelper) {
|
if (this.app.eventHelper) {
|
||||||
for (const eventConfig of this.app.eventHelper.getEventQueue()) {
|
for (const eventConfig of this.app.eventHelper.getEventQueue()) {
|
||||||
for (const [, page] of this.app.pageFragments) {
|
for (const [, page] of this.app.pageFragments) {
|
||||||
const node = page.getNode(eventConfig.toId);
|
const node = page.getNode(eventConfig.toId, { strict: true });
|
||||||
if (node && node === this) {
|
if (node && node === this) {
|
||||||
if (typeof instance[eventConfig.method] === 'function') {
|
if (typeof instance[eventConfig.method] === 'function') {
|
||||||
await instance[eventConfig.method](eventConfig.fromCpt, ...eventConfig.args);
|
await instance[eventConfig.method](eventConfig.fromCpt, ...eventConfig.args);
|
||||||
|
|||||||
@ -84,14 +84,16 @@ class Page extends Node {
|
|||||||
|
|
||||||
public getNode<T extends TMagicNode = TMagicNode>(
|
public getNode<T extends TMagicNode = TMagicNode>(
|
||||||
id: Id,
|
id: Id,
|
||||||
{ iteratorContainerId, iteratorIndex, pageFragmentContainerId }: GetNodeOptions = {},
|
{ iteratorContainerId, iteratorIndex, pageFragmentContainerId, strict }: GetNodeOptions = {},
|
||||||
): T | undefined {
|
): T | undefined {
|
||||||
if (this.nodes.has(id)) {
|
if (this.nodes.has(id)) {
|
||||||
return this.nodes.get(id) as T;
|
return this.nodes.get(id) as T;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pageFragmentContainerId) {
|
if (pageFragmentContainerId) {
|
||||||
return this.app.pageFragments.get(pageFragmentContainerId)?.getNode(id, { iteratorContainerId, iteratorIndex });
|
return this.app.pageFragments
|
||||||
|
.get(pageFragmentContainerId)
|
||||||
|
?.getNode(id, { iteratorContainerId, iteratorIndex, strict: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Array.isArray(iteratorContainerId) && iteratorContainerId.length && Array.isArray(iteratorIndex)) {
|
if (Array.isArray(iteratorContainerId) && iteratorContainerId.length && Array.isArray(iteratorIndex)) {
|
||||||
@ -106,6 +108,14 @@ class Page extends Node {
|
|||||||
|
|
||||||
return iteratorContainer?.getNode(id, iteratorIndex[iteratorIndex.length - 1]) as T;
|
return iteratorContainer?.getNode(id, iteratorIndex[iteratorIndex.length - 1]) as T;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!strict && this.app.pageFragments.size) {
|
||||||
|
for (const [, pageFragment] of this.app.pageFragments) {
|
||||||
|
if (pageFragment.nodes.has(id)) {
|
||||||
|
return pageFragment.nodes.get(id) as T;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public setNode(id: Id, node: TMagicNode) {
|
public setNode(id: Id, node: TMagicNode) {
|
||||||
|
|||||||
@ -48,4 +48,6 @@ export interface GetNodeOptions {
|
|||||||
iteratorContainerId?: Id[];
|
iteratorContainerId?: Id[];
|
||||||
iteratorIndex?: number[];
|
iteratorIndex?: number[];
|
||||||
pageFragmentContainerId?: Id;
|
pageFragmentContainerId?: Id;
|
||||||
|
/** 严格模式,如果为true,页面片中的节点必须指定pageFragmentContainerId,为false时,没有pageFragmentContainerId的时候获得第一个页面片容器中的节点 */
|
||||||
|
strict?: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.6.1",
|
"version": "1.7.2",
|
||||||
"name": "@tmagic/data-source",
|
"name": "@tmagic/data-source",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "dist/tmagic-data-source.umd.cjs",
|
"main": "dist/tmagic-data-source.umd.cjs",
|
||||||
|
|||||||
@ -78,13 +78,13 @@ export const createDataSourceManager = (app: TMagicApp, useMock?: boolean, initi
|
|||||||
replaceChildNode(newNode, [app.page.data]);
|
replaceChildNode(newNode, [app.page.data]);
|
||||||
}
|
}
|
||||||
|
|
||||||
app.getNode(node.id)?.setData(newNode);
|
app.getNode(node.id, { strict: true })?.setData(newNode);
|
||||||
|
|
||||||
for (const [, pageFragment] of app.pageFragments) {
|
for (const [, pageFragment] of app.pageFragments) {
|
||||||
if (pageFragment.data.id === newNode.id) {
|
if (pageFragment.data.id === newNode.id) {
|
||||||
pageFragment.setData(newNode);
|
pageFragment.setData(newNode);
|
||||||
} else if (pageFragment.data.id === page.id) {
|
} else if (pageFragment.data.id === page.id) {
|
||||||
pageFragment.getNode(newNode.id)?.setData(newNode);
|
pageFragment.getNode(newNode.id, { strict: true })?.setData(newNode);
|
||||||
if (!pageFragment.instance) {
|
if (!pageFragment.instance) {
|
||||||
replaceChildNode(newNode, [pageFragment.data]);
|
replaceChildNode(newNode, [pageFragment.data]);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.6.1",
|
"version": "1.7.2",
|
||||||
"name": "@tmagic/dep",
|
"name": "@tmagic/dep",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "dist/tmagic-dep.umd.cjs",
|
"main": "dist/tmagic-dep.umd.cjs",
|
||||||
|
|||||||
@ -55,8 +55,7 @@ export const isIncludeArrayField = (keys: string[], fields: DataSchema[]) => {
|
|||||||
|
|
||||||
// 字段类型为数组并且后面没有数字索引
|
// 字段类型为数组并且后面没有数字索引
|
||||||
return (
|
return (
|
||||||
field &&
|
field?.type === 'array' &&
|
||||||
field.type === 'array' &&
|
|
||||||
// 不是整数
|
// 不是整数
|
||||||
/^(?!\d+$).*$/.test(`${keys[index + 1]}`) &&
|
/^(?!\d+$).*$/.test(`${keys[index + 1]}`) &&
|
||||||
index < keys.length - 1
|
index < keys.length - 1
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.6.1",
|
"version": "1.7.2",
|
||||||
"name": "@tmagic/design",
|
"name": "@tmagic/design",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": [
|
"sideEffects": [
|
||||||
|
|||||||
@ -27,7 +27,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref, watchEffect } from 'vue';
|
import { computed, ref, useTemplateRef, watchEffect } from 'vue';
|
||||||
|
|
||||||
import { getDesignConfig } from './config';
|
import { getDesignConfig } from './config';
|
||||||
import type { AutocompleteProps } from './types';
|
import type { AutocompleteProps } from './types';
|
||||||
@ -58,13 +58,13 @@ const updateModelValue = (...args: any[]) => {
|
|||||||
emit('update:modelValue', ...args);
|
emit('update:modelValue', ...args);
|
||||||
};
|
};
|
||||||
|
|
||||||
const autocomplete = ref<any>();
|
const autocompleteRef = useTemplateRef<any>('autocomplete');
|
||||||
const input = ref<HTMLInputElement>();
|
const input = ref<HTMLInputElement>();
|
||||||
const inputRef = ref<any>();
|
const inputRef = ref<any>();
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
inputRef.value = autocomplete.value?.inputRef;
|
inputRef.value = autocompleteRef.value?.inputRef;
|
||||||
input.value = autocomplete.value?.inputRef.input;
|
input.value = autocompleteRef.value?.inputRef.input;
|
||||||
});
|
});
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
@ -72,10 +72,10 @@ defineExpose({
|
|||||||
input,
|
input,
|
||||||
|
|
||||||
blur: () => {
|
blur: () => {
|
||||||
autocomplete.value?.blur();
|
autocompleteRef.value?.blur();
|
||||||
},
|
},
|
||||||
focus: () => {
|
focus: () => {
|
||||||
autocomplete.value?.focus();
|
autocompleteRef.value?.focus();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<component class="tmagic-design-button" :is="uiComponent" v-bind="uiProps" @click="clickHandler">
|
<component class="tmagic-design-button" :is="uiComponent" v-bind="uiProps" @click="clickHandler">
|
||||||
|
<template #icon v-if="$slots.icon">
|
||||||
|
<slot name="icon"></slot>
|
||||||
|
</template>
|
||||||
<template #default v-if="$slots.default">
|
<template #default v-if="$slots.default">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</template>
|
</template>
|
||||||
@ -30,3 +33,15 @@ const clickHandler = (...args: any[]) => {
|
|||||||
emit('click', ...args);
|
emit('click', ...args);
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.tmagic-design-button {
|
||||||
|
.t-button__text {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ .tmagic-design-button {
|
||||||
|
margin-left: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@ -24,7 +24,11 @@ defineOptions({
|
|||||||
name: 'TMDialog',
|
name: 'TMDialog',
|
||||||
});
|
});
|
||||||
|
|
||||||
const props = defineProps<DialogProps>();
|
const props = withDefaults(defineProps<DialogProps>(), {
|
||||||
|
closeOnClickModal: true,
|
||||||
|
closeOnPressEscape: true,
|
||||||
|
showClose: true,
|
||||||
|
});
|
||||||
|
|
||||||
const emit = defineEmits(['close', 'update:modelValue']);
|
const emit = defineEmits(['close', 'update:modelValue']);
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,11 @@
|
|||||||
<template #label>
|
<template #label>
|
||||||
<slot name="label"></slot>
|
<slot name="label"></slot>
|
||||||
</template>
|
</template>
|
||||||
<slot></slot>
|
|
||||||
|
<template #default>
|
||||||
|
<slot></slot>
|
||||||
|
<div v-if="adapterType === 'element-plus' && extra" v-html="extra" class="m-form-tip"></div>
|
||||||
|
</template>
|
||||||
</component>
|
</component>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -23,5 +27,10 @@ const ui = getDesignConfig('components')?.formItem;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-form-item';
|
const uiComponent = ui?.component || 'el-form-item';
|
||||||
|
|
||||||
const uiProps = computed<FormItemProps>(() => ui?.props(props) || props);
|
const adapterType = getDesignConfig('adapterType');
|
||||||
|
|
||||||
|
const uiProps = computed<FormItemProps>(() => {
|
||||||
|
const { extra, ...rest } = ui?.props(props) || props;
|
||||||
|
return rest;
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -19,3 +19,16 @@ const uiComponent = ui?.component || 'el-icon';
|
|||||||
const props = defineProps<IconProps>();
|
const props = defineProps<IconProps>();
|
||||||
const uiProps = computed<IconProps>(() => ui?.props(props) || props);
|
const uiProps = computed<IconProps>(() => ui?.props(props) || props);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.t-t-design-adapter-icon {
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
width: 1em;
|
||||||
|
height: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@ -7,6 +7,9 @@
|
|||||||
@change="changeHandler"
|
@change="changeHandler"
|
||||||
@input="inputHandler"
|
@input="inputHandler"
|
||||||
@update:modelValue="updateModelValue"
|
@update:modelValue="updateModelValue"
|
||||||
|
@blur="blurHandler"
|
||||||
|
@focus="focusHandler"
|
||||||
|
@click="clickHandler"
|
||||||
>
|
>
|
||||||
<template #prepend v-if="$slots.prepend">
|
<template #prepend v-if="$slots.prepend">
|
||||||
<slot name="prepend"></slot>
|
<slot name="prepend"></slot>
|
||||||
@ -41,7 +44,7 @@ const uiComponent = ui?.component || 'el-input';
|
|||||||
|
|
||||||
const uiProps = computed<InputProps>(() => ui?.props(props) || props);
|
const uiProps = computed<InputProps>(() => ui?.props(props) || props);
|
||||||
|
|
||||||
const emit = defineEmits(['change', 'input', 'update:modelValue']);
|
const emit = defineEmits(['change', 'input', 'blur', 'focus', 'click', 'update:modelValue']);
|
||||||
|
|
||||||
const instance = ref<any>();
|
const instance = ref<any>();
|
||||||
|
|
||||||
@ -57,13 +60,60 @@ const updateModelValue = (...args: any[]) => {
|
|||||||
emit('update:modelValue', ...args);
|
emit('update:modelValue', ...args);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const blurHandler = (...args: any[]) => {
|
||||||
|
emit('blur', ...args);
|
||||||
|
};
|
||||||
|
|
||||||
|
const focusHandler = (...args: any[]) => {
|
||||||
|
emit('focus', ...args);
|
||||||
|
};
|
||||||
|
|
||||||
|
const clickHandler = (...args: any[]) => {
|
||||||
|
emit('click', ...args);
|
||||||
|
};
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
instance,
|
instance,
|
||||||
getInput() {
|
getInput() {
|
||||||
return instance.value.input;
|
if (instance.value.input) {
|
||||||
|
return instance.value.input;
|
||||||
|
}
|
||||||
|
return instance.value?.$el?.querySelector('input');
|
||||||
},
|
},
|
||||||
getTextarea() {
|
getTextarea() {
|
||||||
return instance.value.textarea;
|
if (instance.value.textarea) {
|
||||||
|
return instance.value.textarea;
|
||||||
|
}
|
||||||
|
return instance.value?.$el?.querySelector('textarea');
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.tmagic-design-input {
|
||||||
|
&.t-input-adornment {
|
||||||
|
.t-input-adornment__prepend {
|
||||||
|
> span {
|
||||||
|
border-radius: var(--td-radius-default) 0 0 var(--td-radius-default);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.t-input-adornment__append {
|
||||||
|
> span {
|
||||||
|
border-radius: 0 var(--td-radius-default) var(--td-radius-default) 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.t-input-adornment__prepend,
|
||||||
|
.t-input-adornment__append {
|
||||||
|
> span {
|
||||||
|
display: inline-flex;
|
||||||
|
height: 100%;
|
||||||
|
align-items: center;
|
||||||
|
box-sizing: border-box;
|
||||||
|
white-space: nowrap;
|
||||||
|
padding: 0 var(--td-comp-paddingLR-s);
|
||||||
|
border: 1px solid var(--td-border-level-2-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@ -4,8 +4,9 @@
|
|||||||
:is="uiComponent"
|
:is="uiComponent"
|
||||||
v-bind="uiProps"
|
v-bind="uiProps"
|
||||||
@size-change="handleSizeChange"
|
@size-change="handleSizeChange"
|
||||||
@page-size-change="handleSizeChange"
|
|
||||||
@current-change="handleCurrentChange"
|
@current-change="handleCurrentChange"
|
||||||
|
@update:current-page="updateCurrentPage"
|
||||||
|
@update:page-size="updatePageSize"
|
||||||
></component>
|
></component>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -21,7 +22,7 @@ defineOptions({
|
|||||||
|
|
||||||
const props = defineProps<PaginationProps>();
|
const props = defineProps<PaginationProps>();
|
||||||
|
|
||||||
const emit = defineEmits(['size-change', 'current-change']);
|
const emit = defineEmits(['size-change', 'current-change', 'update:current-page', 'update:page-size']);
|
||||||
|
|
||||||
const ui = getDesignConfig('components')?.pagination;
|
const ui = getDesignConfig('components')?.pagination;
|
||||||
|
|
||||||
@ -35,4 +36,10 @@ const handleSizeChange = (...args: any[]) => {
|
|||||||
const handleCurrentChange = (...args: any[]) => {
|
const handleCurrentChange = (...args: any[]) => {
|
||||||
emit('current-change', ...args);
|
emit('current-change', ...args);
|
||||||
};
|
};
|
||||||
|
const updateCurrentPage = (...args: any[]) => {
|
||||||
|
emit('update:current-page', ...args);
|
||||||
|
};
|
||||||
|
const updatePageSize = (...args: any[]) => {
|
||||||
|
emit('update:page-size', ...args);
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
42
packages/design/src/Popconfirm.vue
Normal file
42
packages/design/src/Popconfirm.vue
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<template>
|
||||||
|
<component
|
||||||
|
class="tmagic-design-popconfirm"
|
||||||
|
:is="uiComponent"
|
||||||
|
v-bind="uiProps"
|
||||||
|
@confirm="confirmHandler"
|
||||||
|
@cancel="cancelHandler"
|
||||||
|
>
|
||||||
|
<template #reference>
|
||||||
|
<slot name="reference"></slot>
|
||||||
|
</template>
|
||||||
|
</component>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed } from 'vue';
|
||||||
|
|
||||||
|
import { getDesignConfig } from './config';
|
||||||
|
import type { PopconfirmProps } from './types';
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'TMPopconfirm',
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['confirm', 'cancel']);
|
||||||
|
|
||||||
|
const props = defineProps<PopconfirmProps>();
|
||||||
|
|
||||||
|
const ui = getDesignConfig('components')?.popconfirm;
|
||||||
|
|
||||||
|
const uiComponent = ui?.component || 'el-popconfirm';
|
||||||
|
|
||||||
|
const uiProps = computed<PopconfirmProps>(() => ui?.props(props) || props);
|
||||||
|
|
||||||
|
const confirmHandler = (...args: any[]) => {
|
||||||
|
emit('confirm', ...args);
|
||||||
|
};
|
||||||
|
|
||||||
|
const cancelHandler = (...args: any[]) => {
|
||||||
|
emit('cancel', ...args);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
@ -25,7 +25,7 @@ defineOptions({
|
|||||||
|
|
||||||
const props = defineProps<SelectProps>();
|
const props = defineProps<SelectProps>();
|
||||||
|
|
||||||
const emit = defineEmits(['change', 'update:modelValue', 'visibleHandler']);
|
const emit = defineEmits(['change', 'update:modelValue', 'visible-change']);
|
||||||
|
|
||||||
const ui = getDesignConfig('components')?.select;
|
const ui = getDesignConfig('components')?.select;
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ const updateModelValue = (...args: any[]) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const visibleHandler = (...args: any[]) => {
|
const visibleHandler = (...args: any[]) => {
|
||||||
emit('visibleHandler', ...args);
|
emit('visible-change', ...args);
|
||||||
};
|
};
|
||||||
|
|
||||||
const scrollbarWrap = ref<HTMLDivElement | undefined>();
|
const scrollbarWrap = ref<HTMLDivElement | undefined>();
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref, watchEffect } from 'vue';
|
import { computed, useTemplateRef } from 'vue';
|
||||||
|
|
||||||
import { getDesignConfig } from './config';
|
import { getDesignConfig } from './config';
|
||||||
import type { TableProps } from './types';
|
import type { TableProps } from './types';
|
||||||
@ -37,7 +37,7 @@ const uiProps = computed<TableProps>(() => ui?.props(props) || props);
|
|||||||
|
|
||||||
const emit = defineEmits(['select', 'sort-change', 'expand-change', 'cell-click']);
|
const emit = defineEmits(['select', 'sort-change', 'expand-change', 'cell-click']);
|
||||||
|
|
||||||
const table = ref<any>();
|
const tableRef = useTemplateRef('table');
|
||||||
|
|
||||||
const selectHandler = (...args: any[]) => {
|
const selectHandler = (...args: any[]) => {
|
||||||
emit('select', ...args);
|
emit('select', ...args);
|
||||||
@ -55,27 +55,21 @@ const cellClickHandler = (...args: any[]) => {
|
|||||||
emit('cell-click', ...args);
|
emit('cell-click', ...args);
|
||||||
};
|
};
|
||||||
|
|
||||||
let $el: HTMLDivElement | undefined;
|
|
||||||
|
|
||||||
watchEffect(() => {
|
|
||||||
$el = table.value?.$el;
|
|
||||||
});
|
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
instance: table,
|
getEl: () => tableRef.value?.getTableRef().$el,
|
||||||
|
|
||||||
$el,
|
getTableRef: () => tableRef.value.getTableRef(),
|
||||||
|
|
||||||
clearSelection(...args: any[]) {
|
clearSelection(...args: any[]) {
|
||||||
return table.value?.clearSelection(...args);
|
return tableRef.value?.clearSelection(...args);
|
||||||
},
|
},
|
||||||
|
|
||||||
toggleRowSelection(...args: any[]) {
|
toggleRowSelection(...args: any[]) {
|
||||||
return table.value?.toggleRowSelection(...args);
|
return tableRef.value?.toggleRowSelection(...args);
|
||||||
},
|
},
|
||||||
|
|
||||||
toggleRowExpansion(...args: any[]) {
|
toggleRowExpansion(...args: any[]) {
|
||||||
return table.value?.toggleRowExpansion(...args);
|
return tableRef.value?.toggleRowExpansion(...args);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -1,27 +0,0 @@
|
|||||||
<template>
|
|
||||||
<component :is="uiComponent" v-bind="uiProps">
|
|
||||||
<template #default="{ $index, row }">
|
|
||||||
<!-- eslint-disable-next-line vue/valid-attribute-name -->
|
|
||||||
<slot :$index="$index" :row="row"></slot>
|
|
||||||
</template>
|
|
||||||
</component>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { computed } from 'vue';
|
|
||||||
|
|
||||||
import { getDesignConfig } from './config';
|
|
||||||
import type { TableColumnProps } from './types';
|
|
||||||
|
|
||||||
defineOptions({
|
|
||||||
name: 'TMTableColumn',
|
|
||||||
});
|
|
||||||
|
|
||||||
const props = defineProps<TableColumnProps>();
|
|
||||||
|
|
||||||
const ui = getDesignConfig('components')?.tableColumn;
|
|
||||||
|
|
||||||
const uiComponent = ui?.component || 'el-table-column';
|
|
||||||
|
|
||||||
const uiProps = computed<TableColumnProps>(() => ui?.props(props) || props);
|
|
||||||
</script>
|
|
||||||
@ -8,6 +8,9 @@
|
|||||||
@tab-remove="onTabRemove"
|
@tab-remove="onTabRemove"
|
||||||
@update:model-value="updateModelName"
|
@update:model-value="updateModelName"
|
||||||
>
|
>
|
||||||
|
<template #add-icon v-if="$slots['add-icon']">
|
||||||
|
<slot name="add-icon"></slot>
|
||||||
|
</template>
|
||||||
<template #default>
|
<template #default>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -1,110 +0,0 @@
|
|||||||
<template>
|
|
||||||
<component
|
|
||||||
class="tmagic-design-tree"
|
|
||||||
ref="tree"
|
|
||||||
:is="uiComponent"
|
|
||||||
v-bind="uiProps"
|
|
||||||
@node-click="nodeClickHandler"
|
|
||||||
@node-contextmenu="contextmenu"
|
|
||||||
@node-drag-end="handleDragEnd"
|
|
||||||
@node-collapse="handleCollapse"
|
|
||||||
@node-expand="handleExpand"
|
|
||||||
@check="checkHandler"
|
|
||||||
@mousedown="mousedownHandler"
|
|
||||||
@mouseup="mouseupHandler"
|
|
||||||
>
|
|
||||||
<template #default="{ data, node }">
|
|
||||||
<slot :data="data" :node="node"></slot>
|
|
||||||
</template>
|
|
||||||
</component>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { computed, ref } from 'vue';
|
|
||||||
|
|
||||||
import { getDesignConfig } from './config';
|
|
||||||
import type { TreeProps } from './types';
|
|
||||||
|
|
||||||
defineOptions({
|
|
||||||
name: 'TMTree',
|
|
||||||
});
|
|
||||||
|
|
||||||
const props = defineProps<TreeProps>();
|
|
||||||
|
|
||||||
const ui = getDesignConfig('components')?.tree;
|
|
||||||
|
|
||||||
const uiComponent = ui?.component || 'el-tree';
|
|
||||||
|
|
||||||
const uiProps = computed<TreeProps>(() => ui?.props(props) || props);
|
|
||||||
|
|
||||||
const emit = defineEmits([
|
|
||||||
'node-click',
|
|
||||||
'node-contextmenu',
|
|
||||||
'node-drag-end',
|
|
||||||
'node-collapse',
|
|
||||||
'node-expand',
|
|
||||||
'check',
|
|
||||||
'mousedown',
|
|
||||||
'mouseup',
|
|
||||||
]);
|
|
||||||
|
|
||||||
const nodeClickHandler = (...args: any[]) => {
|
|
||||||
emit('node-click', ...args);
|
|
||||||
};
|
|
||||||
|
|
||||||
const contextmenu = (...args: any[]) => {
|
|
||||||
emit('node-contextmenu', ...args);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleDragEnd = (...args: any[]) => {
|
|
||||||
emit('node-drag-end', ...args);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleCollapse = (...args: any[]) => {
|
|
||||||
emit('node-collapse', ...args);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleExpand = (...args: any[]) => {
|
|
||||||
emit('node-expand', ...args);
|
|
||||||
};
|
|
||||||
|
|
||||||
const checkHandler = (...args: any[]) => {
|
|
||||||
emit('check', ...args);
|
|
||||||
};
|
|
||||||
|
|
||||||
const mousedownHandler = (...args: any[]) => {
|
|
||||||
emit('mousedown', ...args);
|
|
||||||
};
|
|
||||||
|
|
||||||
const mouseupHandler = (...args: any[]) => {
|
|
||||||
emit('mouseup', ...args);
|
|
||||||
};
|
|
||||||
|
|
||||||
const tree = ref<any>();
|
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
getData() {
|
|
||||||
return tree.value?.data;
|
|
||||||
},
|
|
||||||
|
|
||||||
getStore() {
|
|
||||||
return tree.value?.store;
|
|
||||||
},
|
|
||||||
|
|
||||||
filter(...args: any[]) {
|
|
||||||
return tree.value?.filter(...args);
|
|
||||||
},
|
|
||||||
|
|
||||||
getNode(...args: any[]) {
|
|
||||||
return tree.value?.getNode(...args);
|
|
||||||
},
|
|
||||||
|
|
||||||
setCheckedKeys(...args: any[]) {
|
|
||||||
return tree.value?.setCheckedKeys(...args);
|
|
||||||
},
|
|
||||||
|
|
||||||
setCurrentKey(...args: any[]) {
|
|
||||||
return tree.value?.setCurrentKey(...args);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
@ -46,30 +46,16 @@ export { default as TMagicStep } from './Step.vue';
|
|||||||
export { default as TMagicSteps } from './Steps.vue';
|
export { default as TMagicSteps } from './Steps.vue';
|
||||||
export { default as TMagicSwitch } from './Switch.vue';
|
export { default as TMagicSwitch } from './Switch.vue';
|
||||||
export { default as TMagicTable } from './Table.vue';
|
export { default as TMagicTable } from './Table.vue';
|
||||||
export { default as TMagicTableColumn } from './TableColumn.vue';
|
|
||||||
export { default as TMagicTabPane } from './TabPane.vue';
|
export { default as TMagicTabPane } from './TabPane.vue';
|
||||||
export { default as TMagicTabs } from './Tabs.vue';
|
export { default as TMagicTabs } from './Tabs.vue';
|
||||||
export { default as TMagicTag } from './Tag.vue';
|
export { default as TMagicTag } from './Tag.vue';
|
||||||
export { default as TMagicTimePicker } from './TimePicker.vue';
|
export { default as TMagicTimePicker } from './TimePicker.vue';
|
||||||
export { default as TMagicTooltip } from './Tooltip.vue';
|
export { default as TMagicTooltip } from './Tooltip.vue';
|
||||||
export { default as TMagicTree } from './Tree.vue';
|
|
||||||
export { default as TMagicUpload } from './Upload.vue';
|
export { default as TMagicUpload } from './Upload.vue';
|
||||||
|
export { default as TMagicPopconfirm } from './Popconfirm.vue';
|
||||||
|
|
||||||
export const tMagicMessage = {
|
// eslint-disable-next-line import/no-mutable-exports
|
||||||
error: (msg: string) => {
|
export let tMagicMessage: TMagicMessage;
|
||||||
console.error(msg);
|
|
||||||
},
|
|
||||||
success: (msg: string) => {
|
|
||||||
console.log(msg);
|
|
||||||
},
|
|
||||||
warning: (msg: string) => {
|
|
||||||
console.warn(msg);
|
|
||||||
},
|
|
||||||
info: (msg: string) => {
|
|
||||||
console.info(msg);
|
|
||||||
},
|
|
||||||
closeAll: (_msg: string) => {},
|
|
||||||
} as unknown as TMagicMessage;
|
|
||||||
|
|
||||||
export const tMagicMessageBox = {
|
export const tMagicMessageBox = {
|
||||||
alert: (msg: string) => {
|
alert: (msg: string) => {
|
||||||
@ -109,13 +95,23 @@ export let useZIndex = (zIndexOverrides?: Ref<number>) => {
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
install(app: App, options: DesignPluginOptions) {
|
install(app: App, options: DesignPluginOptions) {
|
||||||
if (options.message) {
|
tMagicMessage =
|
||||||
tMagicMessage.error = options.message?.error;
|
options.message ||
|
||||||
tMagicMessage.success = options.message?.success;
|
({
|
||||||
tMagicMessage.warning = options.message?.warning;
|
error: (msg: string) => {
|
||||||
tMagicMessage.info = options.message?.info;
|
console.error(msg);
|
||||||
tMagicMessage.closeAll = options.message?.closeAll;
|
},
|
||||||
}
|
success: (msg: string) => {
|
||||||
|
console.log(msg);
|
||||||
|
},
|
||||||
|
warning: (msg: string) => {
|
||||||
|
console.warn(msg);
|
||||||
|
},
|
||||||
|
info: (msg: string) => {
|
||||||
|
console.info(msg);
|
||||||
|
},
|
||||||
|
closeAll: (_msg: string) => {},
|
||||||
|
} as unknown as TMagicMessage);
|
||||||
|
|
||||||
if (options.messageBox) {
|
if (options.messageBox) {
|
||||||
tMagicMessageBox.alert = options.messageBox?.alert;
|
tMagicMessageBox.alert = options.messageBox?.alert;
|
||||||
@ -132,6 +128,10 @@ export default {
|
|||||||
useZIndex = options.useZIndex;
|
useZIndex = options.useZIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.adapterType && globalThis.document?.documentElement) {
|
||||||
|
globalThis.document.documentElement.classList.add(`tmagic-adapter-${options.adapterType}`);
|
||||||
|
}
|
||||||
|
|
||||||
app.config.globalProperties.$MAGIC_DESIGN = options;
|
app.config.globalProperties.$MAGIC_DESIGN = options;
|
||||||
setDesignConfig(options);
|
setDesignConfig(options);
|
||||||
},
|
},
|
||||||
|
|||||||
@ -6,7 +6,6 @@ export type FieldSize = 'large' | 'default' | 'small';
|
|||||||
export interface AutocompleteProps {
|
export interface AutocompleteProps {
|
||||||
modelValue?: string;
|
modelValue?: string;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
label?: string;
|
|
||||||
clearable?: boolean;
|
clearable?: boolean;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
triggerOnFocus?: boolean;
|
triggerOnFocus?: boolean;
|
||||||
@ -32,6 +31,7 @@ export interface ButtonProps {
|
|||||||
text?: boolean;
|
text?: boolean;
|
||||||
circle?: boolean;
|
circle?: boolean;
|
||||||
icon?: any;
|
icon?: any;
|
||||||
|
variant?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CardProps {
|
export interface CardProps {
|
||||||
@ -127,6 +127,7 @@ export interface DialogProps {
|
|||||||
closeOnClickModal?: boolean;
|
closeOnClickModal?: boolean;
|
||||||
closeOnPressEscape?: boolean;
|
closeOnPressEscape?: boolean;
|
||||||
destroyOnClose?: boolean;
|
destroyOnClose?: boolean;
|
||||||
|
showClose?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DividerProps {
|
export interface DividerProps {
|
||||||
@ -182,6 +183,8 @@ export interface FormItemProps {
|
|||||||
prop?: string;
|
prop?: string;
|
||||||
labelWidth?: string | number;
|
labelWidth?: string | number;
|
||||||
rules?: any;
|
rules?: any;
|
||||||
|
extra?: string;
|
||||||
|
labelPosition?: 'top' | 'left' | 'right';
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface InputProps {
|
export interface InputProps {
|
||||||
@ -192,6 +195,7 @@ export interface InputProps {
|
|||||||
rows?: number;
|
rows?: number;
|
||||||
type?: string;
|
type?: string;
|
||||||
size?: FieldSize;
|
size?: FieldSize;
|
||||||
|
autosize?: boolean | { minRows: number; maxRows: number };
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface InputNumberProps {
|
export interface InputNumberProps {
|
||||||
@ -222,8 +226,26 @@ export interface PaginationProps {
|
|||||||
hideOnSinglePage?: boolean;
|
hideOnSinglePage?: boolean;
|
||||||
curPage?: number;
|
curPage?: number;
|
||||||
pageSizes?: number[];
|
pageSizes?: number[];
|
||||||
pagesize?: number;
|
pageSize?: number;
|
||||||
total?: number;
|
total?: number;
|
||||||
|
size?: 'large' | 'default' | 'small';
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PopconfirmProps {
|
||||||
|
title?: string;
|
||||||
|
placement?:
|
||||||
|
| 'top'
|
||||||
|
| 'left'
|
||||||
|
| 'right'
|
||||||
|
| 'bottom'
|
||||||
|
| 'top-left'
|
||||||
|
| 'top-right'
|
||||||
|
| 'bottom-left'
|
||||||
|
| 'bottom-right'
|
||||||
|
| 'left-top'
|
||||||
|
| 'left-bottom'
|
||||||
|
| 'right-top'
|
||||||
|
| 'right-bottom';
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PopoverProps {
|
export interface PopoverProps {
|
||||||
@ -295,17 +317,37 @@ export interface SwitchProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface TableProps {
|
export interface TableProps {
|
||||||
|
columns?: TableColumnOptions[];
|
||||||
data?: any[];
|
data?: any[];
|
||||||
border?: boolean;
|
border?: boolean;
|
||||||
maxHeight?: number | string;
|
maxHeight?: number | string;
|
||||||
defaultExpandAll?: boolean;
|
defaultExpandAll?: boolean;
|
||||||
|
showHeader?: boolean;
|
||||||
|
rowKey?: string;
|
||||||
|
treeProps?: Record<string, any>;
|
||||||
|
emptyText?: string;
|
||||||
|
tooltipEffect?: string;
|
||||||
|
tooltipOptions?: any;
|
||||||
|
showOverflowTooltip?: boolean;
|
||||||
|
spanMethod?: (data: any) => any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TableColumnProps {
|
export interface TableColumnOptions<T = any> {
|
||||||
label?: string;
|
props: {
|
||||||
align?: string;
|
class?: string;
|
||||||
fixed?: string | boolean;
|
label?: string;
|
||||||
width?: string | number;
|
fixed?: 'left' | 'right' | boolean;
|
||||||
|
width?: number | string;
|
||||||
|
type?: 'default' | 'selection' | 'index' | 'expand';
|
||||||
|
prop?: string;
|
||||||
|
align?: string;
|
||||||
|
headerAlign?: string;
|
||||||
|
sortable?: boolean;
|
||||||
|
sortOrders?: Array<'ascending' | 'descending'>;
|
||||||
|
selectable?: (row: T, index: number) => boolean;
|
||||||
|
};
|
||||||
|
cell?: (scope: { row: T; $index: number }) => any;
|
||||||
|
title?: (scope?: any) => any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TabPaneProps {
|
export interface TabPaneProps {
|
||||||
@ -317,7 +359,7 @@ export interface TabPaneProps {
|
|||||||
export interface TabsProps {
|
export interface TabsProps {
|
||||||
type?: string;
|
type?: string;
|
||||||
editable?: boolean;
|
editable?: boolean;
|
||||||
tabPosition?: string;
|
tabPosition?: 'left' | 'right' | 'top' | 'bottom';
|
||||||
modelValue?: string | number;
|
modelValue?: string | number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,33 +384,6 @@ export interface TooltipProps {
|
|||||||
offset?: number;
|
offset?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TreeProps {
|
|
||||||
data?: any[];
|
|
||||||
emptyText?: string;
|
|
||||||
nodeKey?: string;
|
|
||||||
props?: any;
|
|
||||||
renderAfterExpand?: boolean;
|
|
||||||
load?: any;
|
|
||||||
renderContent?: any;
|
|
||||||
highlightCurrent?: boolean;
|
|
||||||
defaultExpandAll?: boolean;
|
|
||||||
checkOnClickNode?: boolean;
|
|
||||||
autoExpandParent?: boolean;
|
|
||||||
defaultExpandedKeys?: any[];
|
|
||||||
showCheckbox?: boolean;
|
|
||||||
checkStrictly?: boolean;
|
|
||||||
defaultCheckedKeys?: any[];
|
|
||||||
currentNodeKey?: string | number;
|
|
||||||
filterNodeMethod?: (value: any, data: any, node: any) => boolean;
|
|
||||||
accordion?: boolean;
|
|
||||||
indent?: number;
|
|
||||||
icon?: any;
|
|
||||||
lazy?: boolean;
|
|
||||||
draggable?: boolean;
|
|
||||||
allowDrag?: (node: any) => boolean;
|
|
||||||
allowDrop?: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UploadProps {
|
export interface UploadProps {
|
||||||
action?: string;
|
action?: string;
|
||||||
autoUpload?: boolean;
|
autoUpload?: boolean;
|
||||||
@ -388,7 +403,7 @@ export interface IconProps {
|
|||||||
size?: string;
|
size?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TMagicMessage {
|
interface ExtraApi {
|
||||||
success: (msg: string) => void;
|
success: (msg: string) => void;
|
||||||
warning: (msg: string) => void;
|
warning: (msg: string) => void;
|
||||||
info: (msg: string) => void;
|
info: (msg: string) => void;
|
||||||
@ -396,6 +411,14 @@ export interface TMagicMessage {
|
|||||||
closeAll: () => void;
|
closeAll: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type TMagicMessage = ExtraApi &
|
||||||
|
((options: {
|
||||||
|
type?: 'info' | 'success' | 'warning' | 'error';
|
||||||
|
message?: string;
|
||||||
|
dangerouslyUseHTMLString?: boolean;
|
||||||
|
duration?: number;
|
||||||
|
}) => void);
|
||||||
|
|
||||||
export type ElMessageBoxShortcutMethod = ((
|
export type ElMessageBoxShortcutMethod = ((
|
||||||
message: string,
|
message: string,
|
||||||
title: string,
|
title: string,
|
||||||
@ -635,8 +658,8 @@ export interface Components {
|
|||||||
| DefineComponent<
|
| DefineComponent<
|
||||||
TableProps,
|
TableProps,
|
||||||
{
|
{
|
||||||
instance: any;
|
getEl: () => HTMLElement | undefined;
|
||||||
$el: HTMLDivElement | undefined;
|
getTableRef: () => any;
|
||||||
clearSelection: (...args: any[]) => void;
|
clearSelection: (...args: any[]) => void;
|
||||||
toggleRowSelection: (...args: any[]) => void;
|
toggleRowSelection: (...args: any[]) => void;
|
||||||
toggleRowExpansion: (...args: any[]) => void;
|
toggleRowExpansion: (...args: any[]) => void;
|
||||||
@ -647,11 +670,6 @@ export interface Components {
|
|||||||
props: (props: TableProps) => TableProps;
|
props: (props: TableProps) => TableProps;
|
||||||
};
|
};
|
||||||
|
|
||||||
tableColumn: {
|
|
||||||
component: DefineComponent<TableColumnProps, {}, any> | string;
|
|
||||||
props: (props: TableColumnProps) => TableColumnProps;
|
|
||||||
};
|
|
||||||
|
|
||||||
tabPane: {
|
tabPane: {
|
||||||
component: DefineComponent<TabPaneProps, {}, any> | string;
|
component: DefineComponent<TabPaneProps, {}, any> | string;
|
||||||
props: (props: TabPaneProps) => TabPaneProps;
|
props: (props: TabPaneProps) => TabPaneProps;
|
||||||
@ -677,24 +695,6 @@ export interface Components {
|
|||||||
props: (props: TooltipProps) => TooltipProps;
|
props: (props: TooltipProps) => TooltipProps;
|
||||||
};
|
};
|
||||||
|
|
||||||
tree: {
|
|
||||||
component:
|
|
||||||
| DefineComponent<
|
|
||||||
TreeProps,
|
|
||||||
{
|
|
||||||
getData: () => TreeProps['data'];
|
|
||||||
getStore: () => any;
|
|
||||||
filter: (...args: any[]) => any;
|
|
||||||
getNode: (...args: any[]) => any;
|
|
||||||
setCheckedKeys: (...args: any[]) => any;
|
|
||||||
setCurrentKey: (...args: any[]) => any;
|
|
||||||
},
|
|
||||||
any
|
|
||||||
>
|
|
||||||
| string;
|
|
||||||
props: (props: TreeProps) => TreeProps;
|
|
||||||
};
|
|
||||||
|
|
||||||
upload: {
|
upload: {
|
||||||
component:
|
component:
|
||||||
| DefineComponent<
|
| DefineComponent<
|
||||||
@ -707,9 +707,15 @@ export interface Components {
|
|||||||
| string;
|
| string;
|
||||||
props: (props: UploadProps) => UploadProps;
|
props: (props: UploadProps) => UploadProps;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
popconfirm: {
|
||||||
|
component: DefineComponent<PopconfirmProps, {}, any> | string;
|
||||||
|
props: (props: PopconfirmProps) => PopconfirmProps;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DesignPluginOptions {
|
export interface DesignPluginOptions {
|
||||||
|
adapterType?: string;
|
||||||
message?: TMagicMessage;
|
message?: TMagicMessage;
|
||||||
messageBox?: TMagicMessageBox;
|
messageBox?: TMagicMessageBox;
|
||||||
components?: Components;
|
components?: Components;
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.6.1",
|
"version": "1.7.2",
|
||||||
"name": "@tmagic/editor",
|
"name": "@tmagic/editor",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": [
|
"sideEffects": [
|
||||||
@ -46,31 +46,30 @@
|
|||||||
"typescript"
|
"typescript"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@element-plus/icons-vue": "^2.3.1",
|
"@element-plus/icons-vue": "^2.3.2",
|
||||||
"@tmagic/design": "workspace:*",
|
"@tmagic/design": "workspace:*",
|
||||||
"@tmagic/form": "workspace:*",
|
"@tmagic/form": "workspace:*",
|
||||||
"@tmagic/stage": "workspace:*",
|
"@tmagic/stage": "workspace:*",
|
||||||
"@tmagic/table": "workspace:*",
|
"@tmagic/table": "workspace:*",
|
||||||
"@tmagic/utils": "workspace:*",
|
"@tmagic/utils": "workspace:*",
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
"color": "^3.1.3",
|
|
||||||
"deep-object-diff": "^1.1.9",
|
"deep-object-diff": "^1.1.9",
|
||||||
"emmet-monaco-es": "^5.5.0",
|
"emmet-monaco-es": "^5.6.1",
|
||||||
"events": "^3.3.0",
|
"events": "^3.3.0",
|
||||||
"gesto": "^1.19.4",
|
"gesto": "^1.19.4",
|
||||||
"keycon": "^1.4.0",
|
"keycon": "^1.4.0",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"moveable": "^0.53.0",
|
"moveable": "^0.53.0",
|
||||||
"serialize-javascript": "^6.0.2",
|
"serialize-javascript": "^7.0.0",
|
||||||
"sortablejs": "^1.15.6"
|
"sortablejs": "^1.15.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/events": "^3.0.3",
|
"@types/events": "^3.0.3",
|
||||||
"@types/lodash-es": "^4.17.4",
|
"@types/lodash-es": "^4.17.4",
|
||||||
"@types/serialize-javascript": "^5.0.4",
|
"@types/serialize-javascript": "^5.0.4",
|
||||||
"@types/sortablejs": "^1.15.8",
|
"@types/sortablejs": "^1.15.9",
|
||||||
"@vue/test-utils": "^2.4.6",
|
"@vue/test-utils": "^2.4.6",
|
||||||
"type-fest": "^4.10.3"
|
"type-fest": "^5.2.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@tmagic/core": "workspace:*",
|
"@tmagic/core": "workspace:*",
|
||||||
|
|||||||
@ -201,7 +201,7 @@ const functionConfig = computed<FormConfig>(() => [
|
|||||||
name: 'content',
|
name: 'content',
|
||||||
type: 'vs-code',
|
type: 'vs-code',
|
||||||
options: inject('codeOptions', {}),
|
options: inject('codeOptions', {}),
|
||||||
height: '500px',
|
autosize: { minRows: 10, maxRows: 30 },
|
||||||
onChange: (formState: FormState | undefined, code: string) => {
|
onChange: (formState: FormState | undefined, code: string) => {
|
||||||
try {
|
try {
|
||||||
// 检测js代码是否存在语法错误
|
// 检测js代码是否存在语法错误
|
||||||
|
|||||||
@ -12,13 +12,20 @@
|
|||||||
|
|
||||||
<template v-else-if="data.type === 'button'">
|
<template v-else-if="data.type === 'button'">
|
||||||
<TMagicTooltip v-if="data.tooltip" effect="dark" placement="bottom-start" :content="data.tooltip">
|
<TMagicTooltip v-if="data.tooltip" effect="dark" placement="bottom-start" :content="data.tooltip">
|
||||||
<TMagicButton size="small" link :disabled="disabled"
|
<TMagicButton size="small" link :disabled="disabled">
|
||||||
><MIcon v-if="data.icon" :icon="data.icon"></MIcon><span>{{ data.text }}</span></TMagicButton
|
<template #icon v-if="data.icon">
|
||||||
>
|
<MIcon :icon="data.icon"></MIcon>
|
||||||
|
</template>
|
||||||
|
<template #default v-if="data.text">{{ data.text }}</template>
|
||||||
|
</TMagicButton>
|
||||||
</TMagicTooltip>
|
</TMagicTooltip>
|
||||||
<TMagicButton v-else size="small" link :disabled="disabled" :title="data.text"
|
|
||||||
><MIcon v-if="data.icon" :icon="data.icon"></MIcon><span>{{ data.text }}</span></TMagicButton
|
<TMagicButton v-else size="small" link :disabled="disabled" :title="data.text">
|
||||||
>
|
<template #icon v-if="data.icon">
|
||||||
|
<MIcon :icon="data.icon"></MIcon>
|
||||||
|
</template>
|
||||||
|
<template #default v-if="data.text">{{ data.text }}</template>
|
||||||
|
</TMagicButton>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<TMagicDropdown
|
<TMagicDropdown
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
...config.options,
|
...config.options,
|
||||||
readOnly: disabled,
|
readOnly: disabled,
|
||||||
}"
|
}"
|
||||||
|
:autosize="config.autosize"
|
||||||
:parse="config.parse"
|
:parse="config.parse"
|
||||||
@save="save"
|
@save="save"
|
||||||
></MagicCodeEditor>
|
></MagicCodeEditor>
|
||||||
|
|||||||
@ -2,13 +2,15 @@
|
|||||||
<div class="m-fields-code-select-col">
|
<div class="m-fields-code-select-col">
|
||||||
<div class="code-select-container">
|
<div class="code-select-container">
|
||||||
<!-- 代码块下拉框 -->
|
<!-- 代码块下拉框 -->
|
||||||
<MContainer
|
<MSelect
|
||||||
class="select"
|
class="select"
|
||||||
:config="selectConfig"
|
:config="selectConfig"
|
||||||
|
:name="name"
|
||||||
:model="model"
|
:model="model"
|
||||||
:size="size"
|
:size="size"
|
||||||
|
:prop="prop"
|
||||||
@change="onCodeIdChangeHandler"
|
@change="onCodeIdChangeHandler"
|
||||||
></MContainer>
|
></MSelect>
|
||||||
|
|
||||||
<!-- 查看/编辑按钮 -->
|
<!-- 查看/编辑按钮 -->
|
||||||
<TMagicButton
|
<TMagicButton
|
||||||
@ -28,6 +30,7 @@
|
|||||||
:key="model[name]"
|
:key="model[name]"
|
||||||
:model="model"
|
:model="model"
|
||||||
:size="size"
|
:size="size"
|
||||||
|
:disabled="disabled"
|
||||||
:params-config="paramsConfig"
|
:params-config="paramsConfig"
|
||||||
@change="onParamsChangeHandler"
|
@change="onParamsChangeHandler"
|
||||||
></CodeParams>
|
></CodeParams>
|
||||||
@ -48,7 +51,8 @@ import {
|
|||||||
type FieldProps,
|
type FieldProps,
|
||||||
filterFunction,
|
filterFunction,
|
||||||
type FormState,
|
type FormState,
|
||||||
MContainer,
|
MSelect,
|
||||||
|
type SelectConfig,
|
||||||
} from '@tmagic/form';
|
} from '@tmagic/form';
|
||||||
|
|
||||||
import CodeParams from '@editor/components/CodeParams.vue';
|
import CodeParams from '@editor/components/CodeParams.vue';
|
||||||
@ -108,7 +112,7 @@ watch(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const selectConfig = {
|
const selectConfig: SelectConfig = {
|
||||||
type: 'select',
|
type: 'select',
|
||||||
name: props.name,
|
name: props.name,
|
||||||
disable: props.disabled,
|
disable: props.disabled,
|
||||||
@ -122,33 +126,26 @@ const selectConfig = {
|
|||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
},
|
},
|
||||||
onChange: (formState: any, codeId: Id, { setModel, model }: any) => {
|
|
||||||
// 通过下拉框选择的codeId变化后修正model的值,避免写入其他codeId的params
|
|
||||||
paramsConfig.value = getParamItemsConfig(codeId);
|
|
||||||
|
|
||||||
if (paramsConfig.value.length) {
|
|
||||||
setModel('params', createValues(formState, paramsConfig.value, {}, model.params));
|
|
||||||
} else {
|
|
||||||
setModel('params', {});
|
|
||||||
}
|
|
||||||
|
|
||||||
return codeId;
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const onCodeIdChangeHandler = (value: any, eventData: ContainerChangeEventData) => {
|
const onCodeIdChangeHandler = (value: any) => {
|
||||||
props.model.params = value.params;
|
// 通过下拉框选择的codeId变化后修正model的值,避免写入其他codeId的params
|
||||||
|
paramsConfig.value = getParamItemsConfig(value);
|
||||||
|
|
||||||
emit('change', props.model, {
|
const changeRecords = [
|
||||||
changeRecords: eventData.changeRecords?.map((item) => ({
|
{
|
||||||
prop: `${props.prop.replace(props.name, '')}${item.propPath}`,
|
propPath: props.prop,
|
||||||
value: item.value,
|
value,
|
||||||
})) || [
|
},
|
||||||
{
|
];
|
||||||
propPath: props.prop,
|
|
||||||
value: value[props.name],
|
changeRecords.push({
|
||||||
},
|
propPath: props.prop.replace(`${props.name}`, 'params'),
|
||||||
],
|
value: paramsConfig.value.length ? createValues(mForm, paramsConfig.value, {}, props.model.params) : {},
|
||||||
|
});
|
||||||
|
|
||||||
|
emit('change', value, {
|
||||||
|
changeRecords,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -156,14 +153,10 @@ const onCodeIdChangeHandler = (value: any, eventData: ContainerChangeEventData)
|
|||||||
* 参数值修改更新
|
* 参数值修改更新
|
||||||
*/
|
*/
|
||||||
const onParamsChangeHandler = (value: any, eventData: ContainerChangeEventData) => {
|
const onParamsChangeHandler = (value: any, eventData: ContainerChangeEventData) => {
|
||||||
props.model.params = value.params;
|
eventData.changeRecords?.forEach((record) => {
|
||||||
emit('change', props.model, {
|
record.propPath = `${props.prop.replace(`${props.name}`, '')}${record.propPath}`;
|
||||||
...eventData,
|
|
||||||
changeRecords: (eventData.changeRecords || []).map((item) => ({
|
|
||||||
prop: `${props.prop.replace(props.name, '')}${item.propPath}`,
|
|
||||||
value: item.value,
|
|
||||||
})),
|
|
||||||
});
|
});
|
||||||
|
emit('change', props.model[props.name], eventData);
|
||||||
};
|
};
|
||||||
|
|
||||||
const editCode = (id: string) => {
|
const editCode = (id: string) => {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<TMagicSelect
|
<TMagicSelect
|
||||||
v-model="model[name]"
|
:model-value="model[name]"
|
||||||
clearable
|
clearable
|
||||||
filterable
|
filterable
|
||||||
:size="size"
|
:size="size"
|
||||||
|
|||||||
@ -233,7 +233,6 @@ const dataSourceFieldsConfig: FormConfig = [
|
|||||||
{
|
{
|
||||||
name: 'defaultValue',
|
name: 'defaultValue',
|
||||||
text: '默认值',
|
text: '默认值',
|
||||||
height: '200px',
|
|
||||||
parse: true,
|
parse: true,
|
||||||
type: (mForm: FormState | undefined, { model }: any) => {
|
type: (mForm: FormState | undefined, { model }: any) => {
|
||||||
if (model.type === 'number') return 'number';
|
if (model.type === 'number') return 'number';
|
||||||
@ -242,6 +241,7 @@ const dataSourceFieldsConfig: FormConfig = [
|
|||||||
|
|
||||||
return 'vs-code';
|
return 'vs-code';
|
||||||
},
|
},
|
||||||
|
autosize: { minRows: 1, maxRows: 30 },
|
||||||
options: [
|
options: [
|
||||||
{ text: 'true', value: true },
|
{ text: 'true', value: true },
|
||||||
{ text: 'false', value: false },
|
{ text: 'false', value: false },
|
||||||
@ -267,7 +267,7 @@ const jsonFromConfig: FormConfig = [
|
|||||||
type: 'vs-code',
|
type: 'vs-code',
|
||||||
labelWidth: '0',
|
labelWidth: '0',
|
||||||
language: 'json',
|
language: 'json',
|
||||||
height: '600px',
|
autosize: { minRows: 30, maxRows: 50 },
|
||||||
options: inject('codeOptions', {}),
|
options: inject('codeOptions', {}),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@ -38,12 +38,29 @@
|
|||||||
</template>
|
</template>
|
||||||
</component>
|
</component>
|
||||||
<div
|
<div
|
||||||
:class="`tmagic-data-source-input-text el-input t-input t-size-${size?.[0]} el-input--${size}`"
|
|
||||||
@mouseup="mouseupHandler"
|
|
||||||
v-else
|
v-else
|
||||||
|
:class="{
|
||||||
|
'tmagic-data-source-input-text': true,
|
||||||
|
'el-input': adapterType === 'element-plus',
|
||||||
|
[`el-input--${size}`]: adapterType === 'element-plus',
|
||||||
|
't-input': adapterType === 'tdesign-vue-next',
|
||||||
|
[`t-size-${size?.[0]}`]: adapterType === 'tdesign-vue-next',
|
||||||
|
}"
|
||||||
|
@mouseup="mouseupHandler"
|
||||||
>
|
>
|
||||||
<div :class="`tmagic-data-source-input-text-wrapper el-input__wrapper ${isFocused ? ' is-focus' : ''}`">
|
<div
|
||||||
<div class="el-input__inner t-input__inner">
|
:class="{
|
||||||
|
'tmagic-data-source-input-text-wrapper': true,
|
||||||
|
'el-input__wrapper': adapterType === 'element-plus',
|
||||||
|
'is-focus': isFocused,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
:class="{
|
||||||
|
'el-input__inner': adapterType === 'element-plus',
|
||||||
|
input__inner: adapterType === 'tdesign-vue-next',
|
||||||
|
}"
|
||||||
|
>
|
||||||
<template v-for="(item, index) in displayState">
|
<template v-for="(item, index) in displayState">
|
||||||
<span :key="index" v-if="item.type === 'text'" style="margin-right: 2px">{{ item.value }}</span>
|
<span :key="index" v-if="item.type === 'text'" style="margin-right: 2px">{{ item.value }}</span>
|
||||||
<TMagicTag :key="index" :size="size" v-if="item.type === 'var'">{{ item.value }}</TMagicTag>
|
<TMagicTag :key="index" :size="size" v-if="item.type === 'var'">{{ item.value }}</TMagicTag>
|
||||||
@ -80,6 +97,8 @@ const emit = defineEmits<{
|
|||||||
change: [value: string];
|
change: [value: string];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const adapterType = getDesignConfig('adapterType');
|
||||||
|
|
||||||
const { dataSourceService, propsService } = useServices();
|
const { dataSourceService, propsService } = useServices();
|
||||||
|
|
||||||
const autocompleteRef = useTemplateRef<InstanceType<typeof TMagicAutocomplete>>('autocomplete');
|
const autocompleteRef = useTemplateRef<InstanceType<typeof TMagicAutocomplete>>('autocomplete');
|
||||||
|
|||||||
@ -1,13 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="m-fields-data-source-method-select">
|
<div class="m-fields-data-source-method-select">
|
||||||
<div class="data-source-method-select-container">
|
<div class="data-source-method-select-container">
|
||||||
<MContainer
|
<MCascader
|
||||||
class="select"
|
class="select"
|
||||||
:config="cascaderConfig"
|
:config="cascaderConfig"
|
||||||
:model="model"
|
:model="model"
|
||||||
|
:name="name"
|
||||||
:size="size"
|
:size="size"
|
||||||
|
:disabled="disabled"
|
||||||
|
:prop="prop"
|
||||||
@change="onChangeHandler"
|
@change="onChangeHandler"
|
||||||
></MContainer>
|
></MCascader>
|
||||||
|
|
||||||
<TMagicTooltip
|
<TMagicTooltip
|
||||||
v-if="model[name] && isCustomMethod && hasDataSourceSidePanel"
|
v-if="model[name] && isCustomMethod && hasDataSourceSidePanel"
|
||||||
@ -22,11 +25,12 @@
|
|||||||
<CodeParams
|
<CodeParams
|
||||||
v-if="paramsConfig.length"
|
v-if="paramsConfig.length"
|
||||||
name="params"
|
name="params"
|
||||||
|
:key="model[name]"
|
||||||
:model="model"
|
:model="model"
|
||||||
:size="size"
|
:size="size"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
:params-config="paramsConfig"
|
:params-config="paramsConfig"
|
||||||
@change="onChangeHandler"
|
@change="onParamsChangeHandler"
|
||||||
></CodeParams>
|
></CodeParams>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -38,13 +42,14 @@ import { Edit, View } from '@element-plus/icons-vue';
|
|||||||
import type { Id } from '@tmagic/core';
|
import type { Id } from '@tmagic/core';
|
||||||
import { TMagicButton, TMagicTooltip } from '@tmagic/design';
|
import { TMagicButton, TMagicTooltip } from '@tmagic/design';
|
||||||
import {
|
import {
|
||||||
|
type CascaderConfig,
|
||||||
|
type ContainerChangeEventData,
|
||||||
createValues,
|
createValues,
|
||||||
type DataSourceMethodSelectConfig,
|
type DataSourceMethodSelectConfig,
|
||||||
type FieldProps,
|
type FieldProps,
|
||||||
filterFunction,
|
filterFunction,
|
||||||
type FormState,
|
type FormState,
|
||||||
MContainer,
|
MCascader,
|
||||||
type OnChangeHandlerData,
|
|
||||||
} from '@tmagic/form';
|
} from '@tmagic/form';
|
||||||
|
|
||||||
import CodeParams from '@editor/components/CodeParams.vue';
|
import CodeParams from '@editor/components/CodeParams.vue';
|
||||||
@ -100,21 +105,6 @@ const getParamItemsConfig = ([dataSourceId, methodName]: [Id, string] = ['', '']
|
|||||||
|
|
||||||
const paramsConfig = ref<CodeParamStatement[]>(getParamItemsConfig(props.model[props.name || 'dataSourceMethod']));
|
const paramsConfig = ref<CodeParamStatement[]>(getParamItemsConfig(props.model[props.name || 'dataSourceMethod']));
|
||||||
|
|
||||||
const setParamsConfig = (
|
|
||||||
dataSourceMethod: [Id, string],
|
|
||||||
formState: any = {},
|
|
||||||
setModel: OnChangeHandlerData['setModel'],
|
|
||||||
) => {
|
|
||||||
// 通过下拉框选择的codeId变化后修正model的值,避免写入其他codeId的params
|
|
||||||
paramsConfig.value = dataSourceMethod ? getParamItemsConfig(dataSourceMethod) : [];
|
|
||||||
|
|
||||||
if (paramsConfig.value.length) {
|
|
||||||
setModel('params', createValues(formState, paramsConfig.value, {}, props.model.params));
|
|
||||||
} else {
|
|
||||||
setModel('params', {});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const methodsOptions = computed(
|
const methodsOptions = computed(
|
||||||
() =>
|
() =>
|
||||||
dataSources.value
|
dataSources.value
|
||||||
@ -132,24 +122,42 @@ const methodsOptions = computed(
|
|||||||
})) || [],
|
})) || [],
|
||||||
);
|
);
|
||||||
|
|
||||||
const cascaderConfig = computed(() => ({
|
const cascaderConfig = computed<CascaderConfig>(() => ({
|
||||||
type: 'cascader',
|
type: 'cascader',
|
||||||
name: props.name,
|
|
||||||
options: methodsOptions.value,
|
options: methodsOptions.value,
|
||||||
disable: props.disabled,
|
|
||||||
onChange: (formState: any, dataSourceMethod: [Id, string], { setModel }: OnChangeHandlerData) => {
|
|
||||||
setParamsConfig(dataSourceMethod, formState, setModel);
|
|
||||||
|
|
||||||
return dataSourceMethod;
|
|
||||||
},
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 参数值修改更新
|
* 参数值修改更新
|
||||||
*/
|
*/
|
||||||
const onChangeHandler = (value: any) => {
|
const onChangeHandler = (value: any) => {
|
||||||
props.model.params = value.params;
|
paramsConfig.value = getParamItemsConfig(value);
|
||||||
emit('change', props.model);
|
|
||||||
|
const changeRecords = [
|
||||||
|
{
|
||||||
|
propPath: props.prop,
|
||||||
|
value,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
changeRecords.push({
|
||||||
|
propPath: props.prop.replace(`${props.name}`, 'params'),
|
||||||
|
value: paramsConfig.value.length ? createValues(mForm, paramsConfig.value, {}, props.model.params) : {},
|
||||||
|
});
|
||||||
|
|
||||||
|
emit('change', value, {
|
||||||
|
changeRecords,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 参数值修改更新
|
||||||
|
*/
|
||||||
|
const onParamsChangeHandler = (value: any, eventData: ContainerChangeEventData) => {
|
||||||
|
eventData.changeRecords?.forEach((record) => {
|
||||||
|
record.propPath = `${props.prop.replace(`${props.name}`, '')}${record.propPath}`;
|
||||||
|
});
|
||||||
|
emit('change', props.model[props.name], eventData);
|
||||||
};
|
};
|
||||||
|
|
||||||
const editCodeHandler = () => {
|
const editCodeHandler = () => {
|
||||||
|
|||||||
@ -96,7 +96,7 @@ const formConfig: FormConfig = [
|
|||||||
language: 'json',
|
language: 'json',
|
||||||
options: inject('codeOptions', {}),
|
options: inject('codeOptions', {}),
|
||||||
defaultValue: '{}',
|
defaultValue: '{}',
|
||||||
height: '400px',
|
autosize: { minRows: 30, maxRows: 50 },
|
||||||
onChange: (formState: FormState | undefined, v: string | any) => {
|
onChange: (formState: FormState | undefined, v: string | any) => {
|
||||||
if (typeof v !== 'string') return v;
|
if (typeof v !== 'string') return v;
|
||||||
return JSON.parse(v);
|
return JSON.parse(v);
|
||||||
|
|||||||
@ -55,7 +55,7 @@ const config = computed<GroupListConfig>(() => ({
|
|||||||
{
|
{
|
||||||
type: 'table',
|
type: 'table',
|
||||||
name: 'cond',
|
name: 'cond',
|
||||||
operateColWidth: 100,
|
operateColWidth: 80,
|
||||||
enableToggleMode: false,
|
enableToggleMode: false,
|
||||||
items: [
|
items: [
|
||||||
parentFields.value.length
|
parentFields.value.length
|
||||||
@ -93,7 +93,7 @@ const config = computed<GroupListConfig>(() => ({
|
|||||||
type: 'cond-op-select',
|
type: 'cond-op-select',
|
||||||
parentFields: parentFields.value,
|
parentFields: parentFields.value,
|
||||||
label: '条件',
|
label: '条件',
|
||||||
width: 160,
|
width: 140,
|
||||||
name: 'op',
|
name: 'op',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -219,7 +219,6 @@ const targetCompConfig = computed(() => {
|
|||||||
display: (mForm: FormState, { model }: { model: Record<any, any> }) => model.actionType === ActionType.COMP,
|
display: (mForm: FormState, { model }: { model: Record<any, any> }) => model.actionType === ActionType.COMP,
|
||||||
onChange: (MForm: FormState, v: string, { setModel }: OnChangeHandlerData) => {
|
onChange: (MForm: FormState, v: string, { setModel }: OnChangeHandlerData) => {
|
||||||
setModel('method', '');
|
setModel('method', '');
|
||||||
return v;
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
return { ...defaultTargetCompConfig, ...props.config.targetCompConfig };
|
return { ...defaultTargetCompConfig, ...props.config.targetCompConfig };
|
||||||
|
|||||||
@ -37,12 +37,15 @@
|
|||||||
|
|
||||||
<MagicCodeEditor
|
<MagicCodeEditor
|
||||||
v-if="config.advanced && showCode"
|
v-if="config.advanced && showCode"
|
||||||
height="200px"
|
|
||||||
:init-values="model[name]"
|
:init-values="model[name]"
|
||||||
language="javascript"
|
language="javascript"
|
||||||
:options="{
|
:options="{
|
||||||
readOnly: disabled,
|
readOnly: disabled,
|
||||||
}"
|
}"
|
||||||
|
:autosize="{
|
||||||
|
minRows: 1,
|
||||||
|
maxRows: 20,
|
||||||
|
}"
|
||||||
:parse="true"
|
:parse="true"
|
||||||
@save="save"
|
@save="save"
|
||||||
></MagicCodeEditor>
|
></MagicCodeEditor>
|
||||||
|
|||||||
@ -2,13 +2,16 @@
|
|||||||
<div class="m-fields-page-fragment-select">
|
<div class="m-fields-page-fragment-select">
|
||||||
<div class="page-fragment-select-container">
|
<div class="page-fragment-select-container">
|
||||||
<!-- 页面片下拉框 -->
|
<!-- 页面片下拉框 -->
|
||||||
<m-form-container
|
<MSelect
|
||||||
class="select"
|
class="select"
|
||||||
:config="selectConfig"
|
:config="selectConfig"
|
||||||
:model="model"
|
:model="model"
|
||||||
|
:name="name"
|
||||||
:size="size"
|
:size="size"
|
||||||
|
:prop="prop"
|
||||||
|
:disabled="disabled"
|
||||||
@change="changeHandler"
|
@change="changeHandler"
|
||||||
></m-form-container>
|
></MSelect>
|
||||||
<!-- 编辑按钮 -->
|
<!-- 编辑按钮 -->
|
||||||
<Icon v-if="model[name]" class="icon" :icon="Edit" @click="editPageFragment(model[name])"></Icon>
|
<Icon v-if="model[name]" class="icon" :icon="Edit" @click="editPageFragment(model[name])"></Icon>
|
||||||
</div>
|
</div>
|
||||||
@ -20,7 +23,7 @@ import { computed } from 'vue';
|
|||||||
import { Edit } from '@element-plus/icons-vue';
|
import { Edit } from '@element-plus/icons-vue';
|
||||||
|
|
||||||
import { Id, NodeType } from '@tmagic/core';
|
import { Id, NodeType } from '@tmagic/core';
|
||||||
import { FieldProps, type PageFragmentSelectConfig } from '@tmagic/form';
|
import { FieldProps, MSelect, type PageFragmentSelectConfig, type SelectConfig } from '@tmagic/form';
|
||||||
|
|
||||||
import Icon from '@editor/components/Icon.vue';
|
import Icon from '@editor/components/Icon.vue';
|
||||||
import { useServices } from '@editor/hooks/use-services';
|
import { useServices } from '@editor/hooks/use-services';
|
||||||
@ -32,16 +35,16 @@ defineOptions({
|
|||||||
const { editorService } = useServices();
|
const { editorService } = useServices();
|
||||||
const emit = defineEmits(['change']);
|
const emit = defineEmits(['change']);
|
||||||
|
|
||||||
const props = withDefaults(defineProps<FieldProps<PageFragmentSelectConfig>>(), {
|
withDefaults(defineProps<FieldProps<PageFragmentSelectConfig>>(), {
|
||||||
disabled: false,
|
disabled: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const pageList = computed(() =>
|
const pageList = computed(() =>
|
||||||
editorService.get('root')?.items.filter((item) => item.type === NodeType.PAGE_FRAGMENT),
|
editorService.get('root')?.items.filter((item) => item.type === NodeType.PAGE_FRAGMENT),
|
||||||
);
|
);
|
||||||
|
|
||||||
const selectConfig = {
|
const selectConfig: SelectConfig = {
|
||||||
type: 'select',
|
type: 'select',
|
||||||
name: props.name,
|
|
||||||
options: () => {
|
options: () => {
|
||||||
if (pageList.value) {
|
if (pageList.value) {
|
||||||
return pageList.value.map((item) => ({
|
return pageList.value.map((item) => ({
|
||||||
@ -53,8 +56,8 @@ const selectConfig = {
|
|||||||
return [];
|
return [];
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const changeHandler = async () => {
|
const changeHandler = (v: Id) => {
|
||||||
emit('change', props.model[props.name]);
|
emit('change', v);
|
||||||
};
|
};
|
||||||
|
|
||||||
const editPageFragment = (id: Id) => {
|
const editPageFragment = (id: Id) => {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<TMagicCollapse class="m-fields-style-setter" :model-value="collapseValue">
|
<TMagicCollapse class="m-fields-style-setter" v-model="collapseValue">
|
||||||
<template v-for="(item, index) in list" :key="index">
|
<template v-for="(item, index) in list" :key="index">
|
||||||
<TMagicCollapseItem :name="`${index}`">
|
<TMagicCollapseItem :name="`${index}`">
|
||||||
<template #title><MIcon :icon="Grid"></MIcon>{{ item.title }}</template>
|
<template #title><MIcon :icon="Grid"></MIcon>{{ item.title }}</template>
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
<span class="help-txt" v-if="item.text">{{ item.text }}</span>
|
<span class="help-txt" v-if="item.text">{{ item.text }}</span>
|
||||||
<span class="next-input">
|
<span class="next-input">
|
||||||
<input
|
<input
|
||||||
v-model="model[item.name]"
|
:model-value="model[item.name]"
|
||||||
placeholder="0"
|
placeholder="0"
|
||||||
:title="model[item.name]"
|
:title="model[item.name]"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
<div v-for="(item, index) in list" :key="index" :class="item.class">
|
<div v-for="(item, index) in list" :key="index" :class="item.class">
|
||||||
<span class="next-input">
|
<span class="next-input">
|
||||||
<input
|
<input
|
||||||
v-model="model[item.name]"
|
:model-value="model[item.name]"
|
||||||
placeholder="0"
|
placeholder="0"
|
||||||
:title="model[item.name]"
|
:title="model[item.name]"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
|
|||||||
@ -79,7 +79,6 @@ const clickHandler = ({ detail }: Event & { detail: HTMLElement | MNode }) => {
|
|||||||
id = getIdFromEl()(detail as HTMLElement) || id;
|
id = getIdFromEl()(detail as HTMLElement) || id;
|
||||||
}
|
}
|
||||||
if (id) {
|
if (id) {
|
||||||
props.model[props.name] = id;
|
|
||||||
emit('change', id);
|
emit('change', id);
|
||||||
mForm?.$emit('field-change', props.prop, id);
|
mForm?.$emit('field-change', props.prop, id);
|
||||||
}
|
}
|
||||||
@ -102,7 +101,6 @@ const startSelect = () => {
|
|||||||
|
|
||||||
const deleteHandler = () => {
|
const deleteHandler = () => {
|
||||||
if (props.model) {
|
if (props.model) {
|
||||||
props.model[props.name] = '';
|
|
||||||
emit('change', '');
|
emit('change', '');
|
||||||
mForm?.$emit('field-change', props.prop, '');
|
mForm?.$emit('field-change', props.prop, '');
|
||||||
}
|
}
|
||||||
|
|||||||
@ -92,6 +92,7 @@ export { default as KeyValue } from './fields/KeyValue.vue';
|
|||||||
export { default as CodeBlockList } from './layouts/sidebar/code-block/CodeBlockList.vue';
|
export { default as CodeBlockList } from './layouts/sidebar/code-block/CodeBlockList.vue';
|
||||||
export { default as CodeBlockListPanel } from './layouts/sidebar/code-block/CodeBlockListPanel.vue';
|
export { default as CodeBlockListPanel } from './layouts/sidebar/code-block/CodeBlockListPanel.vue';
|
||||||
export { default as DataSourceConfigPanel } from './layouts/sidebar/data-source/DataSourceConfigPanel.vue';
|
export { default as DataSourceConfigPanel } from './layouts/sidebar/data-source/DataSourceConfigPanel.vue';
|
||||||
|
export { default as DataSourceAddButton } from './layouts/sidebar/data-source/DataSourceAddButton.vue';
|
||||||
export { default as PropsPanel } from './layouts/props-panel/PropsPanel.vue';
|
export { default as PropsPanel } from './layouts/props-panel/PropsPanel.vue';
|
||||||
export { default as PropsFormPanel } from './layouts/props-panel/FormPanel.vue';
|
export { default as PropsFormPanel } from './layouts/props-panel/FormPanel.vue';
|
||||||
export { default as ToolButton } from './components/ToolButton.vue';
|
export { default as ToolButton } from './components/ToolButton.vue';
|
||||||
|
|||||||
@ -1,10 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div :class="`magic-code-editor`">
|
<div :class="`magic-code-editor`">
|
||||||
<Teleport to="body" :disabled="!fullScreen">
|
<Teleport to="body" :disabled="!fullScreen">
|
||||||
<div
|
<div :class="{ 'magic-code-editor-wrapper': true, 'full-screen': fullScreen }" :style="{ height: computeHeight }">
|
||||||
:class="`magic-code-editor-wrapper${fullScreen ? ' full-screen' : ''}`"
|
|
||||||
:style="!fullScreen && height ? `height: ${height}` : '100%'"
|
|
||||||
>
|
|
||||||
<TMagicButton
|
<TMagicButton
|
||||||
v-if="!disabledFullScreen"
|
v-if="!disabledFullScreen"
|
||||||
class="magic-code-editor-full-screen-icon"
|
class="magic-code-editor-full-screen-icon"
|
||||||
@ -20,7 +17,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { nextTick, onBeforeUnmount, onMounted, onUnmounted, ref, useTemplateRef, watch } from 'vue';
|
import { computed, nextTick, onBeforeUnmount, onMounted, onUnmounted, ref, useTemplateRef, watch } from 'vue';
|
||||||
import { FullScreen } from '@element-plus/icons-vue';
|
import { FullScreen } from '@element-plus/icons-vue';
|
||||||
import { throttle } from 'lodash-es';
|
import { throttle } from 'lodash-es';
|
||||||
import serialize from 'serialize-javascript';
|
import serialize from 'serialize-javascript';
|
||||||
@ -46,6 +43,10 @@ const props = withDefaults(
|
|||||||
autoSave?: boolean;
|
autoSave?: boolean;
|
||||||
parse?: boolean;
|
parse?: boolean;
|
||||||
disabledFullScreen?: boolean;
|
disabledFullScreen?: boolean;
|
||||||
|
autosize?: {
|
||||||
|
minRows?: number;
|
||||||
|
maxRows?: number;
|
||||||
|
};
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
initValues: '',
|
initValues: '',
|
||||||
@ -61,6 +62,58 @@ const props = withDefaults(
|
|||||||
|
|
||||||
const emit = defineEmits(['initd', 'save']);
|
const emit = defineEmits(['initd', 'save']);
|
||||||
|
|
||||||
|
const autoHeight = ref<string>('');
|
||||||
|
|
||||||
|
const computeHeight = computed(() => {
|
||||||
|
if (fullScreen.value) {
|
||||||
|
return '100%';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.height) {
|
||||||
|
return props.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.autosize) {
|
||||||
|
return autoHeight.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return '100%';
|
||||||
|
});
|
||||||
|
|
||||||
|
const setAutoHeight = (v = '') => {
|
||||||
|
let lines = Math.max(v.split('\n').length, props.autosize?.minRows || 1);
|
||||||
|
if (v) {
|
||||||
|
if (props.autosize?.maxRows) {
|
||||||
|
lines = Math.min(lines, props.autosize.maxRows);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取编辑器实际行高,如果编辑器还未初始化则使用默认值
|
||||||
|
let lineHeight = 20;
|
||||||
|
if (vsEditor) {
|
||||||
|
const editorOptions = vsEditor.getOptions();
|
||||||
|
lineHeight = editorOptions.get(monaco.editor.EditorOption.lineHeight) || 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newHeight = `${lines * lineHeight + 10}px`;
|
||||||
|
|
||||||
|
// 只有当高度真正改变时才更新
|
||||||
|
if (autoHeight.value !== newHeight) {
|
||||||
|
autoHeight.value = newHeight;
|
||||||
|
|
||||||
|
// 高度变化后需要重新布局编辑器
|
||||||
|
nextTick(() => {
|
||||||
|
vsEditor?.layout();
|
||||||
|
|
||||||
|
// 确保内容在可视区域内,滚动到顶部
|
||||||
|
if (vsEditor) {
|
||||||
|
vsEditor.setScrollTop(0);
|
||||||
|
vsEditor.revealLine(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const toString = (v: string | any, language: string): string => {
|
const toString = (v: string | any, language: string): string => {
|
||||||
let value: string;
|
let value: string;
|
||||||
if (typeof v !== 'string') {
|
if (typeof v !== 'string') {
|
||||||
@ -110,6 +163,8 @@ const resizeObserver = new globalThis.ResizeObserver(
|
|||||||
const setEditorValue = (v: string | any, m: string | any) => {
|
const setEditorValue = (v: string | any, m: string | any) => {
|
||||||
values.value = toString(v, props.language.toLocaleLowerCase());
|
values.value = toString(v, props.language.toLocaleLowerCase());
|
||||||
|
|
||||||
|
setAutoHeight(values.value);
|
||||||
|
|
||||||
if (props.type === 'diff') {
|
if (props.type === 'diff') {
|
||||||
const originalModel = monaco.editor.createModel(values.value, 'text/javascript');
|
const originalModel = monaco.editor.createModel(values.value, 'text/javascript');
|
||||||
const modifiedModel = monaco.editor.createModel(toString(m, props.language), 'text/javascript');
|
const modifiedModel = monaco.editor.createModel(toString(m, props.language), 'text/javascript');
|
||||||
@ -147,6 +202,7 @@ const handleKeyDown = (e: KeyboardEvent) => {
|
|||||||
emit('save', props.parse ? parseCode(newValue, props.language) : newValue);
|
emit('save', props.parse ? parseCode(newValue, props.language) : newValue);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const init = async () => {
|
const init = async () => {
|
||||||
if (!codeEditorEl.value) return;
|
if (!codeEditorEl.value) return;
|
||||||
|
|
||||||
@ -163,8 +219,24 @@ const init = async () => {
|
|||||||
|
|
||||||
if (props.type === 'diff') {
|
if (props.type === 'diff') {
|
||||||
vsDiffEditor = getEditorConfig('customCreateMonacoDiffEditor')(monaco, codeEditorEl.value, options);
|
vsDiffEditor = getEditorConfig('customCreateMonacoDiffEditor')(monaco, codeEditorEl.value, options);
|
||||||
|
|
||||||
|
// 监听diff编辑器内容变化
|
||||||
|
vsDiffEditor.getModifiedEditor().onDidChangeModelContent(() => {
|
||||||
|
// 如果使用 autosize,内容变化时重新计算高度
|
||||||
|
if (props.autosize) {
|
||||||
|
setAutoHeight(getEditorValue());
|
||||||
|
}
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
vsEditor = getEditorConfig('customCreateMonacoEditor')(monaco, codeEditorEl.value, options);
|
vsEditor = getEditorConfig('customCreateMonacoEditor')(monaco, codeEditorEl.value, options);
|
||||||
|
|
||||||
|
// 监听编辑器内容变化
|
||||||
|
vsEditor.onDidChangeModelContent(() => {
|
||||||
|
// 如果使用 autosize,内容变化时重新计算高度
|
||||||
|
if (props.autosize) {
|
||||||
|
setAutoHeight(getEditorValue());
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
setEditorValue(props.initValues, props.modifiedValues);
|
setEditorValue(props.initValues, props.modifiedValues);
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
<SearchInput @search="filterTextChangeHandler"></SearchInput>
|
<SearchInput @search="filterTextChangeHandler"></SearchInput>
|
||||||
|
|
||||||
<slot name="component-list" :component-group-list="list">
|
<slot name="component-list" :component-group-list="list">
|
||||||
<TMagicCollapse class="ui-component-panel" :model-value="collapseValue">
|
<TMagicCollapse class="ui-component-panel" v-model="collapseValue">
|
||||||
<template v-for="(group, index) in list">
|
<template v-for="(group, index) in list">
|
||||||
<TMagicCollapseItem v-if="group.items && group.items.length" :key="index" :name="`${index}`">
|
<TMagicCollapseItem v-if="group.items && group.items.length" :key="index" :name="`${index}`">
|
||||||
<template #title><MIcon :icon="Grid"></MIcon>{{ group.title }}</template>
|
<template #title><MIcon :icon="Grid"></MIcon>{{ group.title }}</template>
|
||||||
@ -34,7 +34,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, inject, ref } from 'vue';
|
import { computed, inject, ref, watch } from 'vue';
|
||||||
import { Grid } from '@element-plus/icons-vue';
|
import { Grid } from '@element-plus/icons-vue';
|
||||||
import serialize from 'serialize-javascript';
|
import serialize from 'serialize-javascript';
|
||||||
|
|
||||||
@ -74,10 +74,19 @@ const list = computed<ComponentGroup[]>(() =>
|
|||||||
items: group.items.filter((item: ComponentItem) => item.text.includes(searchText.value)),
|
items: group.items.filter((item: ComponentItem) => item.text.includes(searchText.value)),
|
||||||
})),
|
})),
|
||||||
);
|
);
|
||||||
const collapseValue = computed(() =>
|
|
||||||
Array(list.value?.length)
|
const collapseValue = ref();
|
||||||
.fill(1)
|
|
||||||
.map((x, i) => `${i}`),
|
watch(
|
||||||
|
list,
|
||||||
|
() => {
|
||||||
|
collapseValue.value = Array(list.value?.length)
|
||||||
|
.fill(1)
|
||||||
|
.map((x, i) => `${i}`);
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
let timeout: ReturnType<typeof setTimeout> | undefined;
|
let timeout: ReturnType<typeof setTimeout> | undefined;
|
||||||
|
|||||||
@ -0,0 +1,46 @@
|
|||||||
|
<template>
|
||||||
|
<TMagicPopover
|
||||||
|
placement="right"
|
||||||
|
trigger="hover"
|
||||||
|
popper-class="data-source-list-panel-add-menu"
|
||||||
|
:destroy-on-close="true"
|
||||||
|
>
|
||||||
|
<template #reference>
|
||||||
|
<TMagicButton v-bind="addButtonConfig || {}">{{ addButtonText || '' }}</TMagicButton>
|
||||||
|
</template>
|
||||||
|
<ToolButton
|
||||||
|
v-for="(item, index) in datasourceTypeList"
|
||||||
|
:data="{
|
||||||
|
type: 'button',
|
||||||
|
text: item.text,
|
||||||
|
handler: () => {
|
||||||
|
$emit('add', item.type);
|
||||||
|
},
|
||||||
|
}"
|
||||||
|
:key="index"
|
||||||
|
></ToolButton>
|
||||||
|
</TMagicPopover>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { type ButtonProps, TMagicButton, TMagicPopover } from '@tmagic/design';
|
||||||
|
|
||||||
|
import ToolButton from '@editor/components/ToolButton.vue';
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'MEditorDataSourceAddButton',
|
||||||
|
});
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
datasourceTypeList: {
|
||||||
|
text: string;
|
||||||
|
type: string;
|
||||||
|
}[];
|
||||||
|
addButtonConfig?: ButtonProps;
|
||||||
|
addButtonText?: string;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
defineEmits<{
|
||||||
|
add: [type: string];
|
||||||
|
}>();
|
||||||
|
</script>
|
||||||
@ -2,28 +2,13 @@
|
|||||||
<TMagicScrollbar class="data-source-list-panel m-editor-layer-panel">
|
<TMagicScrollbar class="data-source-list-panel m-editor-layer-panel">
|
||||||
<div class="search-wrapper">
|
<div class="search-wrapper">
|
||||||
<SearchInput @search="filterTextChangeHandler"></SearchInput>
|
<SearchInput @search="filterTextChangeHandler"></SearchInput>
|
||||||
<TMagicPopover
|
<DataSourceAddButton
|
||||||
v-if="editable"
|
v-if="editable"
|
||||||
placement="right"
|
add-button-text="新增"
|
||||||
trigger="hover"
|
:add-button-config="{ type: 'primary', size: 'small' }"
|
||||||
popper-class="data-source-list-panel-add-menu"
|
:datasource-type-list="datasourceTypeList"
|
||||||
:destroy-on-close="true"
|
@add="addHandler"
|
||||||
>
|
></DataSourceAddButton>
|
||||||
<template #reference>
|
|
||||||
<TMagicButton type="primary" size="small">新增</TMagicButton>
|
|
||||||
</template>
|
|
||||||
<ToolButton
|
|
||||||
v-for="(item, index) in datasourceTypeList"
|
|
||||||
:data="{
|
|
||||||
type: 'button',
|
|
||||||
text: item.text,
|
|
||||||
handler: () => {
|
|
||||||
addHandler(item.type);
|
|
||||||
},
|
|
||||||
}"
|
|
||||||
:key="index"
|
|
||||||
></ToolButton>
|
|
||||||
</TMagicPopover>
|
|
||||||
|
|
||||||
<slot name="data-source-panel-search"></slot>
|
<slot name="data-source-panel-search"></slot>
|
||||||
</div>
|
</div>
|
||||||
@ -63,15 +48,15 @@
|
|||||||
import { computed, inject, useTemplateRef, watch } from 'vue';
|
import { computed, inject, useTemplateRef, watch } from 'vue';
|
||||||
import { mergeWith } from 'lodash-es';
|
import { mergeWith } from 'lodash-es';
|
||||||
|
|
||||||
import { TMagicButton, tMagicMessageBox, TMagicPopover, TMagicScrollbar } from '@tmagic/design';
|
import { tMagicMessageBox, TMagicScrollbar } from '@tmagic/design';
|
||||||
|
|
||||||
import ContentMenu from '@editor/components/ContentMenu.vue';
|
import ContentMenu from '@editor/components/ContentMenu.vue';
|
||||||
import SearchInput from '@editor/components/SearchInput.vue';
|
import SearchInput from '@editor/components/SearchInput.vue';
|
||||||
import ToolButton from '@editor/components/ToolButton.vue';
|
|
||||||
import { useDataSourceEdit } from '@editor/hooks/use-data-source-edit';
|
import { useDataSourceEdit } from '@editor/hooks/use-data-source-edit';
|
||||||
import { useServices } from '@editor/hooks/use-services';
|
import { useServices } from '@editor/hooks/use-services';
|
||||||
import type { CustomContentMenuFunction, DataSourceListSlots, EventBus, MenuButton, MenuComponent } from '@editor/type';
|
import type { CustomContentMenuFunction, DataSourceListSlots, EventBus, MenuButton, MenuComponent } from '@editor/type';
|
||||||
|
|
||||||
|
import DataSourceAddButton from './DataSourceAddButton.vue';
|
||||||
import DataSourceConfigPanel from './DataSourceConfigPanel.vue';
|
import DataSourceConfigPanel from './DataSourceConfigPanel.vue';
|
||||||
import DataSourceList from './DataSourceList.vue';
|
import DataSourceList from './DataSourceList.vue';
|
||||||
import { useContentMenu } from './useContentMenu';
|
import { useContentMenu } from './useContentMenu';
|
||||||
|
|||||||
@ -1,7 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<template v-if="data.type !== 'page'">
|
<template v-if="data.type !== 'page'">
|
||||||
<MIcon v-if="data.visible === false" :icon="Hide" @click.stop="setNodeVisible(true)" title="点击显示"></MIcon>
|
<TMagicButton
|
||||||
<MIcon v-else :icon="View" @click.stop="setNodeVisible(false)" class="node-lock" title="点击隐藏"></MIcon>
|
link
|
||||||
|
:type="data.visible === false ? 'primary' : 'default'"
|
||||||
|
:icon="data.visible === false ? Hide : View"
|
||||||
|
:title="data.visible === false ? '点击显示' : '点击隐藏'"
|
||||||
|
@click.stop="setNodeVisible(data.visible === false)"
|
||||||
|
></TMagicButton>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -9,8 +14,8 @@
|
|||||||
import { Hide, View } from '@element-plus/icons-vue';
|
import { Hide, View } from '@element-plus/icons-vue';
|
||||||
|
|
||||||
import type { MNode } from '@tmagic/core';
|
import type { MNode } from '@tmagic/core';
|
||||||
|
import { TMagicButton } from '@tmagic/design';
|
||||||
|
|
||||||
import MIcon from '@editor/components/Icon.vue';
|
|
||||||
import { useServices } from '@editor/hooks/use-services';
|
import { useServices } from '@editor/hooks/use-services';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
|
|||||||
@ -167,7 +167,7 @@ watch(page, (page) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const resizeObserver = new ResizeObserver((entries) => {
|
const resizeObserver = new globalThis.ResizeObserver((entries) => {
|
||||||
for (const { contentRect } of entries) {
|
for (const { contentRect } of entries) {
|
||||||
uiService.set('stageContainerRect', {
|
uiService.set('stageContainerRect', {
|
||||||
width: contentRect.width,
|
width: contentRect.width,
|
||||||
|
|||||||
@ -574,8 +574,6 @@ class Editor extends BaseService {
|
|||||||
nodes.splice(targetIndex, 1, newConfig);
|
nodes.splice(targetIndex, 1, newConfig);
|
||||||
this.set('nodes', [...nodes]);
|
this.set('nodes', [...nodes]);
|
||||||
|
|
||||||
// update后会触发依赖收集,收集完后会掉stage.update方法
|
|
||||||
|
|
||||||
if (isPage(newConfig) || isPageFragment(newConfig)) {
|
if (isPage(newConfig) || isPageFragment(newConfig)) {
|
||||||
this.set('page', newConfig as MPage | MPageFragment);
|
this.set('page', newConfig as MPage | MPageFragment);
|
||||||
}
|
}
|
||||||
@ -591,6 +589,7 @@ class Editor extends BaseService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新节点
|
* 更新节点
|
||||||
|
* update后会触发依赖收集,收集完后会掉stage.update方法
|
||||||
* @param config 新的节点配置,配置中需要有id信息
|
* @param config 新的节点配置,配置中需要有id信息
|
||||||
* @returns 更新后的节点配置
|
* @returns 更新后的节点配置
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -5,6 +5,22 @@
|
|||||||
|
|
||||||
.m-editor-tree {
|
.m-editor-tree {
|
||||||
padding-top: 48px;
|
padding-top: 48px;
|
||||||
|
|
||||||
|
.tree-node-tool {
|
||||||
|
padding-right: 10px;
|
||||||
|
|
||||||
|
.tmagic-design-button + .tmagic-design-button {
|
||||||
|
margin-left: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-node.selected {
|
||||||
|
.tree-node-tool {
|
||||||
|
.tmagic-design-button {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-wrapper {
|
.search-wrapper {
|
||||||
|
|||||||
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
> div {
|
> div {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
gap: 3px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -76,5 +77,10 @@
|
|||||||
transform: rotate(-90deg);
|
transform: rotate(-90deg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.t-button {
|
||||||
|
padding-left: 1px;
|
||||||
|
padding-right: 1px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,7 +40,7 @@
|
|||||||
top: 0;
|
top: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
z-index: 2;
|
z-index: 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
@use "../common/var" as *;
|
||||||
|
|
||||||
.background-position-container {
|
.background-position-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -6,8 +8,8 @@
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
width: 80px;
|
width: 80px;
|
||||||
height: auto;
|
height: auto;
|
||||||
.el-button {
|
.tmagic-design-button {
|
||||||
& + .el-button {
|
& + .tmagic-design-button {
|
||||||
margin-left: 2px;
|
margin-left: 2px;
|
||||||
}
|
}
|
||||||
&:nth-child(3n + 1) {
|
&:nth-child(3n + 1) {
|
||||||
@ -15,13 +17,18 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.t-button--variant-text {
|
||||||
|
padding-left: 2px;
|
||||||
|
padding-right: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
.position-icon {
|
.position-icon {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 14px;
|
width: 14px;
|
||||||
height: 14px;
|
height: 14px;
|
||||||
border: 1px solid #1d1f24;
|
border: 1px solid #1d1f24;
|
||||||
&.active {
|
&.active {
|
||||||
background-color: var(--el-color-primary);
|
background-color: $theme-color;
|
||||||
&::after {
|
&::after {
|
||||||
border: 1px solid #fff;
|
border: 1px solid #fff;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -64,7 +64,7 @@ const fillConfig = (config: FormConfig): FormConfig => [
|
|||||||
name: 'beforeRequest',
|
name: 'beforeRequest',
|
||||||
type: 'vs-code',
|
type: 'vs-code',
|
||||||
parse: true,
|
parse: true,
|
||||||
height: '600px',
|
autosize: { minRows: 10, maxRows: 30 },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -76,7 +76,7 @@ const fillConfig = (config: FormConfig): FormConfig => [
|
|||||||
name: 'afterResponse',
|
name: 'afterResponse',
|
||||||
type: 'vs-code',
|
type: 'vs-code',
|
||||||
parse: true,
|
parse: true,
|
||||||
height: '600px',
|
autosize: { minRows: 10, maxRows: 30 },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/naming-convention */
|
||||||
/*
|
/*
|
||||||
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -29,11 +29,11 @@ import uiService from '@editor/services/ui';
|
|||||||
|
|
||||||
globalThis.ResizeObserver =
|
globalThis.ResizeObserver =
|
||||||
globalThis.ResizeObserver ||
|
globalThis.ResizeObserver ||
|
||||||
vi.fn().mockImplementation(() => ({
|
class ResizeObserver {
|
||||||
disconnect: vi.fn(),
|
disconnect = vi.fn();
|
||||||
observe: vi.fn(),
|
observe = vi.fn();
|
||||||
unobserve: vi.fn(),
|
unobserve = vi.fn();
|
||||||
}));
|
};
|
||||||
|
|
||||||
describe('Stage.vue', () => {
|
describe('Stage.vue', () => {
|
||||||
(global as any).fetch = vi.fn(() =>
|
(global as any).fetch = vi.fn(() =>
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.6.1",
|
"version": "1.7.2",
|
||||||
"name": "@tmagic/element-plus-adapter",
|
"name": "@tmagic/element-plus-adapter",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "dist/tmagic-element-plus-adapter.umd.cjs",
|
"main": "dist/tmagic-element-plus-adapter.umd.cjs",
|
||||||
@ -37,6 +37,7 @@
|
|||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@tmagic/design": "workspace:*",
|
"@tmagic/design": "workspace:*",
|
||||||
"element-plus": ">=2.9.0",
|
"element-plus": ">=2.9.0",
|
||||||
|
"vue": "catalog:",
|
||||||
"typescript": "catalog:"
|
"typescript": "catalog:"
|
||||||
},
|
},
|
||||||
"peerDependenciesMeta": {
|
"peerDependenciesMeta": {
|
||||||
|
|||||||
95
packages/element-plus-adapter/src/Table.vue
Normal file
95
packages/element-plus-adapter/src/Table.vue
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
<template>
|
||||||
|
<ElTable
|
||||||
|
ref="table"
|
||||||
|
:data="data"
|
||||||
|
:border="border"
|
||||||
|
:max-height="maxHeight"
|
||||||
|
:default-expand-all="defaultExpandAll"
|
||||||
|
:show-header="showHeader"
|
||||||
|
:row-key="rowKey"
|
||||||
|
:tree-props="treeProps"
|
||||||
|
:empty-text="emptyText"
|
||||||
|
:show-overflow-tooltip="showOverflowTooltip"
|
||||||
|
:tooltip-effect="tooltipEffect"
|
||||||
|
:tooltip-options="tooltipOptions"
|
||||||
|
:span-method="spanMethod"
|
||||||
|
@sort-change="sortChange"
|
||||||
|
@select="selectHandler"
|
||||||
|
@select-all="selectAllHandler"
|
||||||
|
@selection-change="selectionChangeHandler"
|
||||||
|
@cell-click="cellClickHandler"
|
||||||
|
@expand-change="expandChange"
|
||||||
|
>
|
||||||
|
<template v-for="(item, columnIndex) in columns" :key="columnIndex">
|
||||||
|
<ElTableColumn v-bind="item.props || {}">
|
||||||
|
<template #header="scope" v-if="item.title">
|
||||||
|
<component :is="item.title(scope)"></component>
|
||||||
|
</template>
|
||||||
|
<template #default="scope" v-if="item.cell">
|
||||||
|
<component :is="item.cell(scope)"></component>
|
||||||
|
</template>
|
||||||
|
</ElTableColumn>
|
||||||
|
</template>
|
||||||
|
</ElTable>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useTemplateRef } from 'vue';
|
||||||
|
import { ElTable, ElTableColumn } from 'element-plus';
|
||||||
|
|
||||||
|
import type { TableProps } from '@tmagic/design';
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'TElAdapterTable',
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['sort-change', 'select', 'select-all', 'selection-change', 'expand-change', 'cell-click']);
|
||||||
|
|
||||||
|
defineProps<TableProps>();
|
||||||
|
|
||||||
|
const tableRef = useTemplateRef('table');
|
||||||
|
|
||||||
|
const sortChange = (data: any) => {
|
||||||
|
emit('sort-change', data);
|
||||||
|
};
|
||||||
|
|
||||||
|
const selectHandler = (...args: any[]) => {
|
||||||
|
emit('select', ...args);
|
||||||
|
};
|
||||||
|
|
||||||
|
const selectAllHandler = (...args: any[]) => {
|
||||||
|
emit('select-all', ...args);
|
||||||
|
};
|
||||||
|
|
||||||
|
const selectionChangeHandler = (...args: any[]) => {
|
||||||
|
emit('selection-change', ...args);
|
||||||
|
};
|
||||||
|
|
||||||
|
const cellClickHandler = (...args: any[]) => {
|
||||||
|
emit('cell-click', ...args);
|
||||||
|
};
|
||||||
|
|
||||||
|
const expandChange = (...args: any[]) => {
|
||||||
|
emit('expand-change', ...args);
|
||||||
|
};
|
||||||
|
|
||||||
|
const toggleRowSelection = (row: any, selected: boolean) => {
|
||||||
|
tableRef.value?.toggleRowSelection(row, selected);
|
||||||
|
};
|
||||||
|
|
||||||
|
const toggleRowExpansion = (row: any, expanded: boolean) => {
|
||||||
|
tableRef.value?.toggleRowExpansion(row, expanded);
|
||||||
|
};
|
||||||
|
|
||||||
|
const clearSelection = () => {
|
||||||
|
tableRef.value?.clearSelection();
|
||||||
|
};
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
getEl: () => tableRef.value?.$el,
|
||||||
|
getTableRef: () => tableRef.value,
|
||||||
|
clearSelection,
|
||||||
|
toggleRowSelection,
|
||||||
|
toggleRowExpansion,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@ -28,6 +28,7 @@ import {
|
|||||||
ElOption,
|
ElOption,
|
||||||
ElOptionGroup,
|
ElOptionGroup,
|
||||||
ElPagination,
|
ElPagination,
|
||||||
|
ElPopconfirm,
|
||||||
ElRadio,
|
ElRadio,
|
||||||
ElRadioButton,
|
ElRadioButton,
|
||||||
ElRadioGroup,
|
ElRadioGroup,
|
||||||
@ -37,14 +38,11 @@ import {
|
|||||||
ElStep,
|
ElStep,
|
||||||
ElSteps,
|
ElSteps,
|
||||||
ElSwitch,
|
ElSwitch,
|
||||||
ElTable,
|
|
||||||
ElTableColumn,
|
|
||||||
ElTabPane,
|
ElTabPane,
|
||||||
ElTabs,
|
ElTabs,
|
||||||
ElTag,
|
ElTag,
|
||||||
ElTimePicker,
|
ElTimePicker,
|
||||||
ElTooltip,
|
ElTooltip,
|
||||||
ElTree,
|
|
||||||
ElUpload,
|
ElUpload,
|
||||||
useZIndex,
|
useZIndex,
|
||||||
} from 'element-plus';
|
} from 'element-plus';
|
||||||
@ -76,6 +74,7 @@ import type {
|
|||||||
OptionGroupProps,
|
OptionGroupProps,
|
||||||
OptionProps,
|
OptionProps,
|
||||||
PaginationProps,
|
PaginationProps,
|
||||||
|
PopconfirmProps,
|
||||||
RadioButtonProps,
|
RadioButtonProps,
|
||||||
RadioGroupProps,
|
RadioGroupProps,
|
||||||
RadioProps,
|
RadioProps,
|
||||||
@ -83,18 +82,19 @@ import type {
|
|||||||
StepProps,
|
StepProps,
|
||||||
StepsProps,
|
StepsProps,
|
||||||
SwitchProps,
|
SwitchProps,
|
||||||
TableColumnProps,
|
|
||||||
TableProps,
|
TableProps,
|
||||||
TabPaneProps,
|
TabPaneProps,
|
||||||
TabsProps,
|
TabsProps,
|
||||||
TagProps,
|
TagProps,
|
||||||
TimePickerProps,
|
TimePickerProps,
|
||||||
TooltipProps,
|
TooltipProps,
|
||||||
TreeProps,
|
|
||||||
UploadProps,
|
UploadProps,
|
||||||
} from '@tmagic/design';
|
} from '@tmagic/design';
|
||||||
|
|
||||||
|
import Table from './Table.vue';
|
||||||
|
|
||||||
const adapter: DesignPluginOptions = {
|
const adapter: DesignPluginOptions = {
|
||||||
|
adapterType: 'element-plus',
|
||||||
useZIndex,
|
useZIndex,
|
||||||
message: ElMessage,
|
message: ElMessage,
|
||||||
messageBox: ElMessageBox,
|
messageBox: ElMessageBox,
|
||||||
@ -111,7 +111,12 @@ const adapter: DesignPluginOptions = {
|
|||||||
|
|
||||||
button: {
|
button: {
|
||||||
component: ElButton as any,
|
component: ElButton as any,
|
||||||
props: (props: ButtonProps) => props,
|
props: (props: ButtonProps) => {
|
||||||
|
return {
|
||||||
|
...props,
|
||||||
|
type: props.type === 'default' ? '' : props.type,
|
||||||
|
};
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
card: {
|
card: {
|
||||||
@ -275,15 +280,10 @@ const adapter: DesignPluginOptions = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
table: {
|
table: {
|
||||||
component: ElTable as any,
|
component: Table as any,
|
||||||
props: (props: TableProps) => props,
|
props: (props: TableProps) => props,
|
||||||
},
|
},
|
||||||
|
|
||||||
tableColumn: {
|
|
||||||
component: ElTableColumn as any,
|
|
||||||
props: (props: TableColumnProps) => props,
|
|
||||||
},
|
|
||||||
|
|
||||||
tabPane: {
|
tabPane: {
|
||||||
component: ElTabPane as any,
|
component: ElTabPane as any,
|
||||||
props: (props: TabPaneProps) => props,
|
props: (props: TabPaneProps) => props,
|
||||||
@ -309,15 +309,15 @@ const adapter: DesignPluginOptions = {
|
|||||||
props: (props: TooltipProps) => props,
|
props: (props: TooltipProps) => props,
|
||||||
},
|
},
|
||||||
|
|
||||||
tree: {
|
|
||||||
component: ElTree as any,
|
|
||||||
props: (props: TreeProps) => props,
|
|
||||||
},
|
|
||||||
|
|
||||||
upload: {
|
upload: {
|
||||||
component: ElUpload as any,
|
component: ElUpload as any,
|
||||||
props: (props: UploadProps) => props,
|
props: (props: UploadProps) => props,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
popconfirm: {
|
||||||
|
component: ElPopconfirm as any,
|
||||||
|
props: (props: PopconfirmProps) => props,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
loading: ElLoading.directive,
|
loading: ElLoading.directive,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.6.1",
|
"version": "1.7.2",
|
||||||
"name": "@tmagic/form-schema",
|
"name": "@tmagic/form-schema",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "dist/tmagic-form-schema.umd.cjs",
|
"main": "dist/tmagic-form-schema.umd.cjs",
|
||||||
|
|||||||
@ -15,13 +15,14 @@ export interface ChangeRecord {
|
|||||||
|
|
||||||
export interface OnChangeHandlerData {
|
export interface OnChangeHandlerData {
|
||||||
model: FormValue;
|
model: FormValue;
|
||||||
values?: FormValue;
|
values?: Readonly<FormValue> | null;
|
||||||
parent?: FormValue;
|
parent?: FormValue;
|
||||||
formValue?: FormValue;
|
formValue?: FormValue;
|
||||||
config: any;
|
config: Readonly<any>;
|
||||||
prop: string;
|
prop: string;
|
||||||
changeRecords: ChangeRecord[];
|
changeRecords: ChangeRecord[];
|
||||||
setModel: (prop: string, value: any) => void;
|
setModel: (prop: string, value: any) => void;
|
||||||
|
setFormValue: (prop: string, value: any) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type FormValue = Record<string | number, any>;
|
export type FormValue = Record<string | number, any>;
|
||||||
@ -40,6 +41,7 @@ export interface FieldProps<T = any> {
|
|||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
size?: 'large' | 'default' | 'small';
|
size?: 'large' | 'default' | 'small';
|
||||||
lastValues?: Record<string, any>;
|
lastValues?: Record<string, any>;
|
||||||
|
isCompare?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -83,6 +85,8 @@ export interface SortProp {
|
|||||||
order: 'ascending' | 'descending';
|
order: 'ascending' | 'descending';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ToolTipConfigType = string | { text?: string; placement?: string };
|
||||||
|
|
||||||
export interface FormItem {
|
export interface FormItem {
|
||||||
/** vnode的key值,默认是遍历数组时的index */
|
/** vnode的key值,默认是遍历数组时的index */
|
||||||
__key?: string | number;
|
__key?: string | number;
|
||||||
@ -98,7 +102,7 @@ export interface FormItem {
|
|||||||
/** 额外的提示信息,和 help 类似,当提示文案同时出现时,可以使用这个。 */
|
/** 额外的提示信息,和 help 类似,当提示文案同时出现时,可以使用这个。 */
|
||||||
extra?: string | FilterFunction<string>;
|
extra?: string | FilterFunction<string>;
|
||||||
/** 配置提示信息 */
|
/** 配置提示信息 */
|
||||||
tooltip?: string | FilterFunction<string>;
|
tooltip?: ToolTipConfigType | FilterFunction<ToolTipConfigType>;
|
||||||
/** 是否置灰 */
|
/** 是否置灰 */
|
||||||
disabled?: boolean | FilterFunction;
|
disabled?: boolean | FilterFunction;
|
||||||
/** 使用表单中的值作为key,例如配置了text,则使用model.text作为key */
|
/** 使用表单中的值作为key,例如配置了text,则使用model.text作为key */
|
||||||
@ -123,6 +127,8 @@ export interface FormItem {
|
|||||||
dynamicKey?: string;
|
dynamicKey?: string;
|
||||||
/** 是否需要显示`展开更多配置` */
|
/** 是否需要显示`展开更多配置` */
|
||||||
expand?: boolean;
|
expand?: boolean;
|
||||||
|
style?: Record<string, any>;
|
||||||
|
fieldStyle?: Record<string, any>;
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,6 +199,7 @@ export type FilterFunction<T = boolean> = (
|
|||||||
prop: string;
|
prop: string;
|
||||||
config: any;
|
config: any;
|
||||||
index?: number;
|
index?: number;
|
||||||
|
getFormValue: (prop: string) => any;
|
||||||
},
|
},
|
||||||
) => T;
|
) => T;
|
||||||
|
|
||||||
@ -343,6 +350,7 @@ export interface DisplayConfig extends FormItem {
|
|||||||
export interface TextConfig extends FormItem, Input {
|
export interface TextConfig extends FormItem, Input {
|
||||||
type?: 'text';
|
type?: 'text';
|
||||||
tooltip?: string;
|
tooltip?: string;
|
||||||
|
prepend?: string;
|
||||||
/** 后置元素,一般为标签或按钮 */
|
/** 后置元素,一般为标签或按钮 */
|
||||||
append?:
|
append?:
|
||||||
| string
|
| string
|
||||||
@ -354,7 +362,10 @@ export interface TextConfig extends FormItem, Input {
|
|||||||
mForm: FormState | undefined,
|
mForm: FormState | undefined,
|
||||||
data: {
|
data: {
|
||||||
model: any;
|
model: any;
|
||||||
values: any;
|
values?: Readonly<FormValue> | null;
|
||||||
|
formValue?: FormValue;
|
||||||
|
setModel: (prop: string, value: any) => void;
|
||||||
|
setFormValue: (prop: string, value: any) => void;
|
||||||
},
|
},
|
||||||
) => void;
|
) => void;
|
||||||
};
|
};
|
||||||
@ -366,6 +377,7 @@ export interface TextConfig extends FormItem, Input {
|
|||||||
export interface TextareaConfig extends FormItem {
|
export interface TextareaConfig extends FormItem {
|
||||||
type: 'textarea';
|
type: 'textarea';
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
|
rows?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -385,6 +397,7 @@ export interface NumberConfig extends FormItem {
|
|||||||
*/
|
*/
|
||||||
export interface NumberRangeConfig extends FormItem {
|
export interface NumberRangeConfig extends FormItem {
|
||||||
type?: 'number-range';
|
type?: 'number-range';
|
||||||
|
clearable?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -429,6 +442,7 @@ export interface CheckboxConfig extends FormItem {
|
|||||||
type: 'checkbox';
|
type: 'checkbox';
|
||||||
activeValue?: number | string;
|
activeValue?: number | string;
|
||||||
inactiveValue?: number | string;
|
inactiveValue?: number | string;
|
||||||
|
useLabel?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -543,7 +557,8 @@ export interface LinkConfig extends FormItem {
|
|||||||
mForm: FormState | undefined,
|
mForm: FormState | undefined,
|
||||||
data: {
|
data: {
|
||||||
model: Record<any, any>;
|
model: Record<any, any>;
|
||||||
values: Record<any, any>;
|
values?: Readonly<FormValue> | null;
|
||||||
|
formValue?: FormValue;
|
||||||
},
|
},
|
||||||
) => FormConfig);
|
) => FormConfig);
|
||||||
fullscreen?: boolean;
|
fullscreen?: boolean;
|
||||||
@ -640,7 +655,13 @@ export interface TabConfig extends FormItem, ContainerCommonConfig {
|
|||||||
*/
|
*/
|
||||||
export interface FieldsetConfig extends FormItem, ContainerCommonConfig {
|
export interface FieldsetConfig extends FormItem, ContainerCommonConfig {
|
||||||
type: 'fieldset';
|
type: 'fieldset';
|
||||||
checkbox?: boolean;
|
checkbox?:
|
||||||
|
| boolean
|
||||||
|
| {
|
||||||
|
name: string;
|
||||||
|
trueValue?: string | number;
|
||||||
|
falseValue?: string | number;
|
||||||
|
};
|
||||||
expand?: boolean;
|
expand?: boolean;
|
||||||
legend?: string;
|
legend?: string;
|
||||||
schematic?: string;
|
schematic?: string;
|
||||||
@ -698,14 +719,24 @@ export interface TableConfig extends FormItem {
|
|||||||
onSelect?: (mForm: FormState | undefined, data: any) => any;
|
onSelect?: (mForm: FormState | undefined, data: any) => any;
|
||||||
defautSort?: SortProp;
|
defautSort?: SortProp;
|
||||||
defaultSort?: SortProp;
|
defaultSort?: SortProp;
|
||||||
|
/** 是否支持拖拽排序 */
|
||||||
dropSort?: boolean;
|
dropSort?: boolean;
|
||||||
|
dropSortHandle?: boolean;
|
||||||
|
dropActionButtonIcon?: any;
|
||||||
|
copyActionButtonIcon?: any;
|
||||||
|
deleteActionButtonIcon?: any;
|
||||||
/** 是否显示全屏按钮 */
|
/** 是否显示全屏按钮 */
|
||||||
enableFullscreen?: boolean;
|
enableFullscreen?: boolean;
|
||||||
fixed?: boolean;
|
fixed?: boolean | 'left' | 'right';
|
||||||
itemExtra?: string | FilterFunction<string>;
|
itemExtra?: string | FilterFunction<string>;
|
||||||
|
titleTip?: FilterFunction<string>;
|
||||||
rowKey?: string;
|
rowKey?: string;
|
||||||
/** table 新增行时前置回调 */
|
/** table 新增行时前置回调 */
|
||||||
beforeAddRow?: (mForm: FormState | undefined, data: any) => boolean;
|
beforeAddRow?: (mForm: FormState | undefined, data: any) => boolean;
|
||||||
|
addButtonConfig?: {
|
||||||
|
props?: Record<string, any>;
|
||||||
|
text?: string;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GroupListConfig extends FormItem {
|
export interface GroupListConfig extends FormItem {
|
||||||
@ -737,6 +768,10 @@ export interface GroupListConfig extends FormItem {
|
|||||||
groupModel: any,
|
groupModel: any,
|
||||||
) => boolean | boolean;
|
) => boolean | boolean;
|
||||||
moveSpecifyLocation?: boolean;
|
moveSpecifyLocation?: boolean;
|
||||||
|
addButtonConfig?: {
|
||||||
|
props?: Record<string, any>;
|
||||||
|
text?: string;
|
||||||
|
};
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -758,6 +793,10 @@ export interface ComponentConfig extends FormItem {
|
|||||||
display: any;
|
display: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface FlexLayoutConfig extends FormItem, ContainerCommonConfig {
|
||||||
|
type: 'flex-layout';
|
||||||
|
}
|
||||||
|
|
||||||
export type ChildConfig =
|
export type ChildConfig =
|
||||||
| FormItem
|
| FormItem
|
||||||
| TabConfig
|
| TabConfig
|
||||||
|
|||||||
@ -39,6 +39,10 @@ export interface CodeConfig extends FormItem {
|
|||||||
};
|
};
|
||||||
height?: string;
|
height?: string;
|
||||||
parse?: boolean;
|
parse?: boolean;
|
||||||
|
autosize?: {
|
||||||
|
minRows?: number;
|
||||||
|
maxRows?: number;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CodeLinkConfig extends FormItem {
|
export interface CodeLinkConfig extends FormItem {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.6.1",
|
"version": "1.7.2",
|
||||||
"name": "@tmagic/form",
|
"name": "@tmagic/form",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": [
|
"sideEffects": [
|
||||||
@ -37,15 +37,15 @@
|
|||||||
"url": "https://github.com/Tencent/tmagic-editor.git"
|
"url": "https://github.com/Tencent/tmagic-editor.git"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@element-plus/icons-vue": "^2.3.1",
|
"@element-plus/icons-vue": "^2.3.2",
|
||||||
"@popperjs/core": "^2.11.8",
|
"@popperjs/core": "^2.11.8",
|
||||||
"dayjs": "^1.11.11",
|
"dayjs": "^1.11.19",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"sortablejs": "^1.15.2"
|
"sortablejs": "^1.15.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/lodash-es": "^4.17.4",
|
"@types/lodash-es": "^4.17.4",
|
||||||
"@types/sortablejs": "^1.15.8",
|
"@types/sortablejs": "^1.15.9",
|
||||||
"@vue/test-utils": "^2.4.6"
|
"@vue/test-utils": "^2.4.6"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
|||||||
@ -28,10 +28,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { provide, reactive, ref, shallowRef, toRaw, watch, watchEffect } from 'vue';
|
import { provide, reactive, ref, shallowRef, toRaw, useTemplateRef, watch, watchEffect } from 'vue';
|
||||||
import { cloneDeep, isEqual } from 'lodash-es';
|
import { cloneDeep, isEqual } from 'lodash-es';
|
||||||
|
|
||||||
import { TMagicForm, tMagicMessage, tMagicMessageBox } from '@tmagic/design';
|
import { TMagicForm, tMagicMessage, tMagicMessageBox } from '@tmagic/design';
|
||||||
|
import { setValueByKeyPath } from '@tmagic/utils';
|
||||||
|
|
||||||
import Container from './containers/Container.vue';
|
import Container from './containers/Container.vue';
|
||||||
import { getConfig } from './utils/config';
|
import { getConfig } from './utils/config';
|
||||||
@ -83,7 +84,7 @@ const props = withDefaults(
|
|||||||
|
|
||||||
const emit = defineEmits(['change', 'error', 'field-input', 'field-change', 'update:stepActive']);
|
const emit = defineEmits(['change', 'error', 'field-input', 'field-change', 'update:stepActive']);
|
||||||
|
|
||||||
const tMagicForm = ref<InstanceType<typeof TMagicForm>>();
|
const tMagicFormRef = useTemplateRef('tMagicForm');
|
||||||
const initialized = ref(false);
|
const initialized = ref(false);
|
||||||
const values = ref<FormValue>({});
|
const values = ref<FormValue>({});
|
||||||
const lastValuesProcessed = ref<FormValue>({});
|
const lastValuesProcessed = ref<FormValue>({});
|
||||||
@ -173,7 +174,18 @@ watch(
|
|||||||
|
|
||||||
const changeHandler = (v: FormValue, eventData: ContainerChangeEventData) => {
|
const changeHandler = (v: FormValue, eventData: ContainerChangeEventData) => {
|
||||||
if (eventData.changeRecords?.length) {
|
if (eventData.changeRecords?.length) {
|
||||||
changeRecords.value.push(...eventData.changeRecords);
|
for (const record of eventData.changeRecords) {
|
||||||
|
if (record.propPath) {
|
||||||
|
const index = changeRecords.value.findIndex((item) => item.propPath === record.propPath);
|
||||||
|
if (index > -1) {
|
||||||
|
changeRecords.value[index] = record;
|
||||||
|
} else {
|
||||||
|
changeRecords.value.push(record);
|
||||||
|
}
|
||||||
|
|
||||||
|
setValueByKeyPath(record.propPath, record.value, values.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
emit('change', values.value, eventData);
|
emit('change', values.value, eventData);
|
||||||
};
|
};
|
||||||
@ -184,6 +196,46 @@ const submitHandler = (e: SubmitEvent) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过 name 从 config 中查找对应的 text
|
||||||
|
* @param name - 字段名,支持点分隔的路径格式,如 'a.b.c'
|
||||||
|
* @param config - 表单配置数组
|
||||||
|
* @returns 找到的 text 值,如果未找到则返回 undefined
|
||||||
|
*/
|
||||||
|
const getTextByName = (name: string, config: FormConfig = props.config): string | undefined => {
|
||||||
|
if (!name || !Array.isArray(config)) return undefined;
|
||||||
|
|
||||||
|
const nameParts = name.split('.');
|
||||||
|
|
||||||
|
const findInConfig = (configs: FormConfig, parts: string[]): string | undefined => {
|
||||||
|
if (parts.length === 0) return undefined;
|
||||||
|
|
||||||
|
const [currentPart, ...remainingParts] = parts;
|
||||||
|
|
||||||
|
for (const item of configs) {
|
||||||
|
if (item.name === currentPart) {
|
||||||
|
if (remainingParts.length === 0) {
|
||||||
|
return typeof item.text === 'string' ? item.text : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.items && Array.isArray(item.items)) {
|
||||||
|
const result = findInConfig(item.items, remainingParts);
|
||||||
|
if (result !== undefined) return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.items && Array.isArray(item.items)) {
|
||||||
|
const result = findInConfig(item.items, parts);
|
||||||
|
if (result !== undefined) return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
return findInConfig(config, nameParts);
|
||||||
|
};
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
values,
|
values,
|
||||||
lastValuesProcessed,
|
lastValuesProcessed,
|
||||||
@ -194,29 +246,38 @@ defineExpose({
|
|||||||
changeHandler,
|
changeHandler,
|
||||||
|
|
||||||
resetForm: () => {
|
resetForm: () => {
|
||||||
tMagicForm.value?.resetFields();
|
tMagicFormRef.value?.resetFields();
|
||||||
changeRecords.value = [];
|
changeRecords.value = [];
|
||||||
},
|
},
|
||||||
|
|
||||||
submitForm: async (native?: boolean): Promise<any> => {
|
submitForm: async (native?: boolean): Promise<any> => {
|
||||||
try {
|
try {
|
||||||
await tMagicForm.value?.validate();
|
const result = await tMagicFormRef.value?.validate();
|
||||||
|
// tdesign 错误通过返回值返回
|
||||||
|
// element-plus 通过throw error
|
||||||
|
if (result !== true) {
|
||||||
|
throw result;
|
||||||
|
}
|
||||||
|
changeRecords.value = [];
|
||||||
return native ? values.value : cloneDeep(toRaw(values.value));
|
return native ? values.value : cloneDeep(toRaw(values.value));
|
||||||
} catch (invalidFields: any) {
|
} catch (invalidFields: any) {
|
||||||
emit('error', invalidFields);
|
emit('error', invalidFields);
|
||||||
|
|
||||||
const error: string[] = [];
|
const error: string[] = [];
|
||||||
|
|
||||||
Object.entries(invalidFields).forEach(([, ValidateError]) => {
|
Object.entries(invalidFields).forEach(([prop, ValidateError]) => {
|
||||||
(ValidateError as ValidateError[]).forEach(({ field, message }) => {
|
(ValidateError as ValidateError[]).forEach(({ field, message }) => {
|
||||||
if (field && message) error.push(`${field} -> ${message}`);
|
const name = field || prop;
|
||||||
if (field && !message) error.push(`${field} -> 出现错误`);
|
const text = getTextByName(name, props.config) || name;
|
||||||
if (!field && message) error.push(`${message}`);
|
|
||||||
|
error.push(`${text} -> ${message}`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
throw new Error(error.join('<br>'));
|
throw new Error(error.join('<br>'));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getTextByName,
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -101,8 +101,9 @@ watchEffect(() => {
|
|||||||
|
|
||||||
const submitHandler = async () => {
|
const submitHandler = async () => {
|
||||||
try {
|
try {
|
||||||
|
const changeRecords = form.value?.changeRecords;
|
||||||
const values = await form.value?.submitForm();
|
const values = await form.value?.submitForm();
|
||||||
emit('submit', values, { changeRecords: form.value?.changeRecords });
|
emit('submit', values, { changeRecords });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit('error', e);
|
emit('error', e);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,10 @@
|
|||||||
:width="width"
|
:width="width"
|
||||||
:zIndex="zIndex"
|
:zIndex="zIndex"
|
||||||
:fullscreen="fullscreen"
|
:fullscreen="fullscreen"
|
||||||
:close-on-click-modal="false"
|
:close-on-click-modal="closeOnClickModal"
|
||||||
|
:close-on-press-escape="closeOnPressEscape"
|
||||||
|
:destroy-on-close="destroyOnClose"
|
||||||
|
:show-close="showClose"
|
||||||
@close="closeHandler"
|
@close="closeHandler"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@ -42,7 +45,7 @@
|
|||||||
</TMagicCol>
|
</TMagicCol>
|
||||||
<TMagicCol :span="12">
|
<TMagicCol :span="12">
|
||||||
<slot name="footer">
|
<slot name="footer">
|
||||||
<TMagicButton @click="cancel" size="small">取 消</TMagicButton>
|
<TMagicButton v-if="showCancel" @click="cancel" size="small">取 消</TMagicButton>
|
||||||
<TMagicButton v-if="hasStep && stepActive > 1" type="info" size="small" @click="preStep"
|
<TMagicButton v-if="hasStep && stepActive > 1" type="info" size="small" @click="preStep"
|
||||||
>上一步</TMagicButton
|
>上一步</TMagicButton
|
||||||
>
|
>
|
||||||
@ -87,11 +90,21 @@ const props = withDefaults(
|
|||||||
size?: 'small' | 'default' | 'large';
|
size?: 'small' | 'default' | 'large';
|
||||||
confirmText?: string;
|
confirmText?: string;
|
||||||
preventSubmitDefault?: boolean;
|
preventSubmitDefault?: boolean;
|
||||||
|
closeOnClickModal?: boolean;
|
||||||
|
closeOnPressEscape?: boolean;
|
||||||
|
destroyOnClose?: boolean;
|
||||||
|
showClose?: boolean;
|
||||||
|
showCancel?: boolean;
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
config: () => [],
|
config: () => [],
|
||||||
values: () => ({}),
|
values: () => ({}),
|
||||||
confirmText: '确定',
|
confirmText: '确定',
|
||||||
|
closeOnClickModal: false,
|
||||||
|
closeOnPressEscape: false,
|
||||||
|
destroyOnClose: false,
|
||||||
|
showClose: true,
|
||||||
|
showCancel: true,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -131,8 +144,9 @@ const closeHandler = () => {
|
|||||||
|
|
||||||
const save = async () => {
|
const save = async () => {
|
||||||
try {
|
try {
|
||||||
|
const changeRecords = form.value?.changeRecords;
|
||||||
const values = await form.value?.submitForm();
|
const values = await form.value?.submitForm();
|
||||||
emit('submit', values, { changeRecords: form.value?.changeRecords });
|
emit('submit', values, { changeRecords });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit('error', e);
|
emit('error', e);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -109,8 +109,9 @@ watchEffect(() => {
|
|||||||
|
|
||||||
const submitHandler = async () => {
|
const submitHandler = async () => {
|
||||||
try {
|
try {
|
||||||
|
const changeRecords = form.value?.changeRecords;
|
||||||
const values = await form.value?.submitForm();
|
const values = await form.value?.submitForm();
|
||||||
emit('submit', values, { changeRecords: form.value?.changeRecords });
|
emit('submit', values, { changeRecords });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit('error', e);
|
emit('error', e);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,87 +1,67 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
v-if="config"
|
|
||||||
:data-tmagic-id="config.id"
|
:data-tmagic-id="config.id"
|
||||||
:data-tmagic-form-item-prop="itemProp"
|
:data-tmagic-form-item-prop="itemProp"
|
||||||
:style="config.tip ? 'display: flex;align-items: baseline;' : ''"
|
:class="`m-form-container m-container-${type || ''} ${config.className || ''}${config.tip ? ' has-tip' : ''}`"
|
||||||
:class="`m-form-container m-container-${type || ''} ${config.className || ''}`"
|
:style="config.style"
|
||||||
>
|
>
|
||||||
<m-fields-hidden
|
<m-fields-hidden v-if="type === 'hidden'" v-bind="fieldsProps" :model="model"></m-fields-hidden>
|
||||||
v-if="type === 'hidden'"
|
|
||||||
:model="model"
|
|
||||||
:config="config"
|
|
||||||
:name="config.name"
|
|
||||||
:disabled="disabled"
|
|
||||||
:prop="itemProp"
|
|
||||||
></m-fields-hidden>
|
|
||||||
|
|
||||||
<component
|
<component
|
||||||
v-else-if="items && !text && type && display"
|
v-else-if="items && !text && type && display"
|
||||||
:key="key(config)"
|
v-bind="fieldsProps"
|
||||||
:size="size"
|
|
||||||
:is="tagName"
|
:is="tagName"
|
||||||
:model="model"
|
:model="model"
|
||||||
:last-values="lastValues"
|
:last-values="lastValues"
|
||||||
:is-compare="isCompare"
|
:is-compare="isCompare"
|
||||||
:config="config"
|
|
||||||
:disabled="disabled"
|
|
||||||
:name="name"
|
|
||||||
:prop="itemProp"
|
|
||||||
:step-active="stepActive"
|
:step-active="stepActive"
|
||||||
:expand-more="expand"
|
:expand-more="expand"
|
||||||
:label-width="itemLabelWidth"
|
:label-width="itemLabelWidth"
|
||||||
|
:style="config.fieldStyle"
|
||||||
@change="onChangeHandler"
|
@change="onChangeHandler"
|
||||||
@addDiffCount="onAddDiffCount"
|
@addDiffCount="onAddDiffCount"
|
||||||
></component>
|
></component>
|
||||||
|
|
||||||
<template v-else-if="type && display && !showDiff">
|
<template v-else-if="type && display && !showDiff">
|
||||||
<TMagicFormItem
|
<TMagicFormItem v-bind="formItemProps" :class="{ 'tmagic-form-hidden': `${itemLabelWidth}` === '0' || !text }">
|
||||||
:style="config.tip ? 'flex: 1' : ''"
|
<template #label>
|
||||||
:class="{ 'tmagic-form-hidden': `${itemLabelWidth}` === '0' || !text }"
|
<FormLabel
|
||||||
:prop="itemProp"
|
:tip="config.tip"
|
||||||
:label-width="itemLabelWidth"
|
:type="type"
|
||||||
:label-position="config.labelPosition"
|
:use-label="config.useLabel"
|
||||||
:rules="rule"
|
:label-title="config.labelTitle"
|
||||||
>
|
:text="text"
|
||||||
<template #label><span v-html="type === 'checkbox' ? '' : text" :title="config.labelTitle"></span></template>
|
></FormLabel>
|
||||||
<TMagicTooltip v-if="tooltip">
|
</template>
|
||||||
|
|
||||||
|
<TMagicTooltip v-if="tooltip.text" :placement="tooltip.placement">
|
||||||
<component
|
<component
|
||||||
:key="key(config)"
|
v-bind="fieldsProps"
|
||||||
:size="size"
|
|
||||||
:is="tagName"
|
:is="tagName"
|
||||||
:model="model"
|
:model="model"
|
||||||
:last-values="lastValues"
|
:last-values="lastValues"
|
||||||
:config="config"
|
:is-compare="isCompare"
|
||||||
:name="name"
|
|
||||||
:disabled="disabled"
|
|
||||||
:prop="itemProp"
|
|
||||||
@change="onChangeHandler"
|
@change="onChangeHandler"
|
||||||
@addDiffCount="onAddDiffCount"
|
@addDiffCount="onAddDiffCount"
|
||||||
></component>
|
></component>
|
||||||
<template #content>
|
<template #content>
|
||||||
<div v-html="tooltip"></div>
|
<div v-html="tooltip.text"></div>
|
||||||
</template>
|
</template>
|
||||||
</TMagicTooltip>
|
</TMagicTooltip>
|
||||||
|
|
||||||
<component
|
<component
|
||||||
v-else
|
v-else
|
||||||
:key="key(config)"
|
v-bind="fieldsProps"
|
||||||
:size="size"
|
|
||||||
:is="tagName"
|
:is="tagName"
|
||||||
:model="model"
|
:model="model"
|
||||||
:last-values="lastValues"
|
:last-values="lastValues"
|
||||||
:config="config"
|
:is-compare="isCompare"
|
||||||
:name="name"
|
|
||||||
:disabled="disabled"
|
|
||||||
:prop="itemProp"
|
|
||||||
@change="onChangeHandler"
|
@change="onChangeHandler"
|
||||||
@addDiffCount="onAddDiffCount"
|
@addDiffCount="onAddDiffCount"
|
||||||
></component>
|
></component>
|
||||||
|
|
||||||
<div v-if="extra && type !== 'table'" v-html="extra" class="m-form-tip"></div>
|
|
||||||
</TMagicFormItem>
|
</TMagicFormItem>
|
||||||
|
|
||||||
<TMagicTooltip v-if="config.tip" placement="left">
|
<TMagicTooltip v-if="config.tip && type === 'checkbox' && !config.useLabel" placement="top">
|
||||||
<TMagicIcon style="line-height: 40px; margin-left: 5px"><warning-filled /></TMagicIcon>
|
<TMagicIcon style="line-height: 40px; margin-left: 5px"><warning-filled /></TMagicIcon>
|
||||||
<template #content>
|
<template #content>
|
||||||
<div v-html="config.tip"></div>
|
<div v-html="config.tip"></div>
|
||||||
@ -93,99 +73,61 @@
|
|||||||
<template v-else-if="type && display && showDiff">
|
<template v-else-if="type && display && showDiff">
|
||||||
<!-- 上次内容 -->
|
<!-- 上次内容 -->
|
||||||
<TMagicFormItem
|
<TMagicFormItem
|
||||||
:style="config.tip ? 'flex: 1' : ''"
|
v-bind="formItemProps"
|
||||||
:class="{ 'tmagic-form-hidden': `${itemLabelWidth}` === '0' || !text }"
|
:class="{ 'tmagic-form-hidden': `${itemLabelWidth}` === '0' || !text, 'show-diff': true }"
|
||||||
:prop="itemProp"
|
|
||||||
:label-width="itemLabelWidth"
|
|
||||||
:label-position="config.labelPosition"
|
|
||||||
:rules="rule"
|
|
||||||
style="background: #f7dadd"
|
|
||||||
>
|
>
|
||||||
<template #label><span v-html="type === 'checkbox' ? '' : text" :title="config.labelTitle"></span></template>
|
<template #label>
|
||||||
<TMagicTooltip v-if="tooltip">
|
<FormLabel
|
||||||
<component
|
:tip="config.tip"
|
||||||
:key="key(config)"
|
:type="type"
|
||||||
:size="size"
|
:use-label="config.useLabel"
|
||||||
:is="tagName"
|
:label-title="config.labelTitle"
|
||||||
:model="lastValues"
|
:text="text"
|
||||||
:config="config"
|
></FormLabel>
|
||||||
:name="name"
|
</template>
|
||||||
:disabled="disabled"
|
<TMagicTooltip v-if="tooltip.text" :placement="tooltip.placement">
|
||||||
:prop="itemProp"
|
<component v-bind="fieldsProps" :is="tagName" :model="lastValues" @change="onChangeHandler"></component>
|
||||||
@change="onChangeHandler"
|
|
||||||
></component>
|
|
||||||
<template #content>
|
<template #content>
|
||||||
<div v-html="tooltip"></div>
|
<div v-html="tooltip.text"></div>
|
||||||
</template>
|
</template>
|
||||||
</TMagicTooltip>
|
</TMagicTooltip>
|
||||||
|
|
||||||
<component
|
<component v-else v-bind="fieldsProps" :is="tagName" :model="lastValues" @change="onChangeHandler"></component>
|
||||||
v-else
|
|
||||||
:key="key(config)"
|
|
||||||
:size="size"
|
|
||||||
:is="tagName"
|
|
||||||
:model="lastValues"
|
|
||||||
:config="config"
|
|
||||||
:name="name"
|
|
||||||
:disabled="disabled"
|
|
||||||
:prop="itemProp"
|
|
||||||
@change="onChangeHandler"
|
|
||||||
></component>
|
|
||||||
|
|
||||||
<div v-if="extra" v-html="extra" class="m-form-tip"></div>
|
|
||||||
</TMagicFormItem>
|
</TMagicFormItem>
|
||||||
|
|
||||||
<TMagicTooltip v-if="config.tip" placement="left">
|
<TMagicTooltip v-if="config.tip && type === 'checkbox' && !config.useLabel" placement="top">
|
||||||
<TMagicIcon style="line-height: 40px; margin-left: 5px"><warning-filled /></TMagicIcon>
|
<TMagicIcon style="line-height: 40px; margin-left: 5px"><warning-filled /></TMagicIcon>
|
||||||
<template #content>
|
<template #content>
|
||||||
<div v-html="config.tip"></div>
|
<div v-html="config.tip"></div>
|
||||||
</template>
|
</template>
|
||||||
</TMagicTooltip>
|
</TMagicTooltip>
|
||||||
|
|
||||||
<!-- 当前内容 -->
|
<!-- 当前内容 -->
|
||||||
<TMagicFormItem
|
<TMagicFormItem
|
||||||
|
v-bind="formItemProps"
|
||||||
:style="config.tip ? 'flex: 1' : ''"
|
:style="config.tip ? 'flex: 1' : ''"
|
||||||
:class="{ 'tmagic-form-hidden': `${itemLabelWidth}` === '0' || !text }"
|
:class="{ 'tmagic-form-hidden': `${itemLabelWidth}` === '0' || !text, 'show-diff': true }"
|
||||||
:prop="itemProp"
|
|
||||||
:label-width="itemLabelWidth"
|
|
||||||
:label-position="config.labelPosition"
|
|
||||||
:rules="rule"
|
|
||||||
style="background: #def7da"
|
|
||||||
>
|
>
|
||||||
<template #label><span v-html="type === 'checkbox' ? '' : text" :title="config.labelTitle"></span></template>
|
<template #label>
|
||||||
<TMagicTooltip v-if="tooltip">
|
<FormLabel
|
||||||
<component
|
:tip="config.tip"
|
||||||
:key="key(config)"
|
:type="type"
|
||||||
:size="size"
|
:use-label="config.useLabel"
|
||||||
:is="tagName"
|
:label-title="config.labelTitle"
|
||||||
:model="model"
|
:text="text"
|
||||||
:config="config"
|
></FormLabel>
|
||||||
:name="name"
|
</template>
|
||||||
:disabled="disabled"
|
<TMagicTooltip v-if="tooltip.text" :placement="tooltip.placement">
|
||||||
:prop="itemProp"
|
<component v-bind="fieldsProps" :is="tagName" :model="model" @change="onChangeHandler"></component>
|
||||||
@change="onChangeHandler"
|
|
||||||
></component>
|
|
||||||
<template #content>
|
<template #content>
|
||||||
<div v-html="tooltip"></div>
|
<div v-html="tooltip.text"></div>
|
||||||
</template>
|
</template>
|
||||||
</TMagicTooltip>
|
</TMagicTooltip>
|
||||||
|
|
||||||
<component
|
<component v-else v-bind="fieldsProps" :is="tagName" :model="model" @change="onChangeHandler"></component>
|
||||||
v-else
|
|
||||||
:key="key(config)"
|
|
||||||
:size="size"
|
|
||||||
:is="tagName"
|
|
||||||
:model="model"
|
|
||||||
:config="config"
|
|
||||||
:name="name"
|
|
||||||
:disabled="disabled"
|
|
||||||
:prop="itemProp"
|
|
||||||
@change="onChangeHandler"
|
|
||||||
></component>
|
|
||||||
|
|
||||||
<div v-if="extra" v-html="extra" class="m-form-tip"></div>
|
|
||||||
</TMagicFormItem>
|
</TMagicFormItem>
|
||||||
|
|
||||||
<TMagicTooltip v-if="config.tip" placement="left">
|
<TMagicTooltip v-if="config.tip && type === 'checkbox' && !config.useLabel" placement="top">
|
||||||
<TMagicIcon style="line-height: 40px; margin-left: 5px"><warning-filled /></TMagicIcon>
|
<TMagicIcon style="line-height: 40px; margin-left: 5px"><warning-filled /></TMagicIcon>
|
||||||
<template #content>
|
<template #content>
|
||||||
<div v-html="config.tip"></div>
|
<div v-html="config.tip"></div>
|
||||||
@ -223,16 +165,25 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, inject, ref, toRaw, watch, watchEffect } from 'vue';
|
import { computed, inject, readonly, ref, toRaw, watch, watchEffect } from 'vue';
|
||||||
import { WarningFilled } from '@element-plus/icons-vue';
|
import { WarningFilled } from '@element-plus/icons-vue';
|
||||||
import { isEqual } from 'lodash-es';
|
import { isEqual } from 'lodash-es';
|
||||||
|
|
||||||
import { TMagicButton, TMagicFormItem, TMagicIcon, TMagicTooltip } from '@tmagic/design';
|
import { TMagicButton, TMagicFormItem, TMagicIcon, TMagicTooltip } from '@tmagic/design';
|
||||||
import { setValueByKeyPath } from '@tmagic/utils';
|
import { getValueByKeyPath } from '@tmagic/utils';
|
||||||
|
|
||||||
import type { ChildConfig, ContainerChangeEventData, ContainerCommonConfig, FormState, FormValue } from '../schema';
|
import type {
|
||||||
|
ChildConfig,
|
||||||
|
ContainerChangeEventData,
|
||||||
|
ContainerCommonConfig,
|
||||||
|
FormState,
|
||||||
|
FormValue,
|
||||||
|
ToolTipConfigType,
|
||||||
|
} from '../schema';
|
||||||
import { display as displayFunction, filterFunction, getRules } from '../utils/form';
|
import { display as displayFunction, filterFunction, getRules } from '../utils/form';
|
||||||
|
|
||||||
|
import FormLabel from './FormLabel.vue';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'MFormContainer',
|
name: 'MFormContainer',
|
||||||
});
|
});
|
||||||
@ -284,10 +235,7 @@ const items = computed(() => (props.config as ContainerCommonConfig).items);
|
|||||||
|
|
||||||
const itemProp = computed(() => {
|
const itemProp = computed(() => {
|
||||||
let n: string | number = '';
|
let n: string | number = '';
|
||||||
const { names } = props.config as any;
|
if (name.value) {
|
||||||
if (names?.[0]) {
|
|
||||||
[n] = names;
|
|
||||||
} else if (name.value) {
|
|
||||||
n = name.value;
|
n = name.value;
|
||||||
} else {
|
} else {
|
||||||
return props.prop;
|
return props.prop;
|
||||||
@ -311,9 +259,20 @@ const disabled = computed(() => props.disabled || filterFunction(mForm, props.co
|
|||||||
|
|
||||||
const text = computed(() => filterFunction(mForm, props.config.text, props));
|
const text = computed(() => filterFunction(mForm, props.config.text, props));
|
||||||
|
|
||||||
const tooltip = computed(() => filterFunction(mForm, props.config.tooltip, props));
|
const tooltip = computed(() => {
|
||||||
|
const config = filterFunction<ToolTipConfigType>(mForm, props.config.tooltip, props);
|
||||||
|
if (typeof config === 'string') {
|
||||||
|
return {
|
||||||
|
text: config,
|
||||||
|
placement: 'top',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const extra = computed(() => filterFunction(mForm, props.config.extra, props));
|
return {
|
||||||
|
text: config?.text,
|
||||||
|
placement: config?.placement || 'top',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
const rule = computed(() => getRules(mForm, props.config.rules, props));
|
const rule = computed(() => getRules(mForm, props.config.rules, props));
|
||||||
|
|
||||||
@ -334,6 +293,24 @@ const display = computed((): boolean => {
|
|||||||
return value;
|
return value;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const fieldsProps = computed(() => ({
|
||||||
|
size: props.size,
|
||||||
|
config: props.config,
|
||||||
|
name: name.value,
|
||||||
|
disabled: disabled.value,
|
||||||
|
prop: itemProp.value,
|
||||||
|
key: props.config[mForm?.keyProps],
|
||||||
|
style: props.config.fieldStyle,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const formItemProps = computed(() => ({
|
||||||
|
prop: itemProp.value,
|
||||||
|
labelWidth: itemLabelWidth.value,
|
||||||
|
labelPosition: props.config.labelPosition,
|
||||||
|
rules: rule.value,
|
||||||
|
extra: filterFunction(mForm, props.config.extra, props),
|
||||||
|
}));
|
||||||
|
|
||||||
const itemLabelWidth = computed(() => props.config.labelWidth ?? props.labelWidth);
|
const itemLabelWidth = computed(() => props.config.labelWidth ?? props.labelWidth);
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
@ -367,6 +344,7 @@ const filterHandler = (filter: any, value: FormValue | number | string) => {
|
|||||||
formValue: mForm?.values,
|
formValue: mForm?.values,
|
||||||
prop: itemProp.value,
|
prop: itemProp.value,
|
||||||
config: props.config,
|
config: props.config,
|
||||||
|
getFormValue: (prop: string) => getValueByKeyPath(prop, mForm?.values || props.model),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,8 +384,29 @@ const isValidName = () => {
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const createModelProxy = (
|
||||||
|
target: any,
|
||||||
|
setModelFn: (_key: string, _value: any) => void,
|
||||||
|
pathPrefix: string = '',
|
||||||
|
): any => {
|
||||||
|
return new Proxy(target, {
|
||||||
|
get: (obj, key: string) => {
|
||||||
|
const value = obj[key];
|
||||||
|
if (value && typeof value === 'object') {
|
||||||
|
const newPath = pathPrefix ? `${pathPrefix}.${key}` : key;
|
||||||
|
return createModelProxy(value, setModelFn, newPath);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
set: (obj, key: string, value) => {
|
||||||
|
setModelFn(pathPrefix ? `${pathPrefix}.${key}` : key, value);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const onChangeHandler = async function (v: any, eventData: ContainerChangeEventData = {}) {
|
const onChangeHandler = async function (v: any, eventData: ContainerChangeEventData = {}) {
|
||||||
const { filter, onChange, trim, dynamicKey } = props.config as any;
|
const { filter, onChange, trim } = props.config as any;
|
||||||
let value: FormValue | number | string | any[] = toRaw(v);
|
let value: FormValue | number | string | any[] = toRaw(v);
|
||||||
const changeRecords = eventData.changeRecords || [];
|
const changeRecords = eventData.changeRecords || [];
|
||||||
const newChangeRecords = [...changeRecords];
|
const newChangeRecords = [...changeRecords];
|
||||||
@ -416,20 +415,29 @@ const onChangeHandler = async function (v: any, eventData: ContainerChangeEventD
|
|||||||
value = filterHandler(filter, v);
|
value = filterHandler(filter, v);
|
||||||
|
|
||||||
if (typeof onChange === 'function') {
|
if (typeof onChange === 'function') {
|
||||||
|
const setModel = (key: string, value: any) => {
|
||||||
|
if (props.config.name) {
|
||||||
|
newChangeRecords.push({ propPath: itemProp.value.replace(`${props.config.name}`, key), value });
|
||||||
|
} else {
|
||||||
|
newChangeRecords.push({ propPath: itemProp.value, value });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const setFormValue = (key: string, value: any) => {
|
||||||
|
newChangeRecords.push({ propPath: key, value });
|
||||||
|
};
|
||||||
|
|
||||||
value =
|
value =
|
||||||
(await onChange(mForm, value, {
|
(await onChange(mForm, value, {
|
||||||
model: props.model,
|
model: createModelProxy(props.model, setModel),
|
||||||
values: mForm?.initValues,
|
values: mForm ? readonly(mForm.initValues) : null,
|
||||||
formValue: mForm?.values,
|
formValue: createModelProxy(mForm?.values || {}, setFormValue),
|
||||||
prop: itemProp.value,
|
prop: itemProp.value,
|
||||||
config: props.config,
|
config: props.config,
|
||||||
changeRecords: newChangeRecords,
|
changeRecords: newChangeRecords,
|
||||||
setModel: (key: string, value: any) => {
|
setModel,
|
||||||
setValueByKeyPath(key, value, props.model);
|
setFormValue,
|
||||||
if (props.config.name) {
|
getFormValue: (prop: string) => getValueByKeyPath(prop, mForm?.values || props.model),
|
||||||
newChangeRecords.push({ propPath: itemProp.value.replace(`${props.config.name}`, key), value });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})) ?? value;
|
})) ?? value;
|
||||||
}
|
}
|
||||||
value = trimHandler(trim, value) ?? value;
|
value = trimHandler(trim, value) ?? value;
|
||||||
@ -440,19 +448,10 @@ const onChangeHandler = async function (v: any, eventData: ContainerChangeEventD
|
|||||||
let valueProp = itemProp.value;
|
let valueProp = itemProp.value;
|
||||||
|
|
||||||
if (hasModifyKey(eventData)) {
|
if (hasModifyKey(eventData)) {
|
||||||
if (dynamicKey) {
|
|
||||||
props.model[eventData.modifyKey!] = value;
|
|
||||||
} else if (isValidName()) {
|
|
||||||
props.model[name.value][eventData.modifyKey!] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
valueProp = valueProp ? `${valueProp}.${eventData.modifyKey}` : eventData.modifyKey!;
|
valueProp = valueProp ? `${valueProp}.${eventData.modifyKey}` : eventData.modifyKey!;
|
||||||
|
|
||||||
// 需要清除掉modifyKey,不然往上层抛出后还会被认为需要修改
|
// 需要清除掉modifyKey,不然往上层抛出后还会被认为需要修改
|
||||||
delete eventData.modifyKey;
|
delete eventData.modifyKey;
|
||||||
} else if (isValidName() && props.model !== value && (v !== value || props.model[name.value] !== value)) {
|
|
||||||
// field内容下包含field-link时,model===value, 这里避免循环引用
|
|
||||||
props.model[name.value] = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changeRecords.length === 0) {
|
if (changeRecords.length === 0) {
|
||||||
|
|||||||
@ -2,10 +2,10 @@
|
|||||||
<fieldset v-if="name ? model[name] : model" class="m-fieldset" :style="show ? 'padding: 15px' : 'border: 0'">
|
<fieldset v-if="name ? model[name] : model" class="m-fieldset" :style="show ? 'padding: 15px' : 'border: 0'">
|
||||||
<component v-if="name && config.checkbox" :is="!show ? 'div' : 'legend'">
|
<component v-if="name && config.checkbox" :is="!show ? 'div' : 'legend'">
|
||||||
<TMagicCheckbox
|
<TMagicCheckbox
|
||||||
v-model="model[name].value"
|
:model-value="(name ? model[name] : model)[checkboxName]"
|
||||||
:prop="`${prop}${prop ? '.' : ''}${config.name}.value`"
|
:prop="`${prop}${prop ? '.' : ''}${config.name}.${checkboxName}`"
|
||||||
:true-value="1"
|
:true-value="checkboxTrueValue"
|
||||||
:false-value="0"
|
:false-value="checkboxFalseValue"
|
||||||
@update:modelValue="valueChangeHandler"
|
@update:modelValue="valueChangeHandler"
|
||||||
><span v-html="config.legend"></span><span v-if="config.extra" v-html="config.extra" class="m-form-tip"></span
|
><span v-html="config.legend"></span><span v-if="config.extra" v-html="config.extra" class="m-form-tip"></span
|
||||||
></TMagicCheckbox>
|
></TMagicCheckbox>
|
||||||
@ -99,9 +99,33 @@ const mForm = inject<FormState | undefined>('mForm');
|
|||||||
|
|
||||||
const name = computed(() => props.config.name || '');
|
const name = computed(() => props.config.name || '');
|
||||||
|
|
||||||
|
const checkboxName = computed(() => {
|
||||||
|
if (typeof props.config.checkbox === 'object' && typeof props.config.checkbox.name === 'string') {
|
||||||
|
return props.config.checkbox.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'value';
|
||||||
|
});
|
||||||
|
|
||||||
|
const checkboxTrueValue = computed(() => {
|
||||||
|
if (typeof props.config.checkbox === 'object' && typeof props.config.checkbox.trueValue !== 'undefined') {
|
||||||
|
return props.config.checkbox.trueValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
const checkboxFalseValue = computed(() => {
|
||||||
|
if (typeof props.config.checkbox === 'object' && typeof props.config.checkbox.falseValue !== 'undefined') {
|
||||||
|
return props.config.checkbox.falseValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
const show = computed(() => {
|
const show = computed(() => {
|
||||||
if (props.config.expand && name.value) {
|
if (props.config.expand && checkboxName.value) {
|
||||||
return props.model[name.value]?.value;
|
return (name.value ? props.model[name.value] : props.model)?.[checkboxName.value] === checkboxTrueValue.value;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
@ -114,7 +138,7 @@ const lWidth = computed(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const valueChangeHandler = (value: number | boolean) => {
|
const valueChangeHandler = (value: number | boolean) => {
|
||||||
emit('change', value, { modifyKey: 'value' });
|
emit('change', value, { modifyKey: checkboxName.value });
|
||||||
};
|
};
|
||||||
|
|
||||||
const changeHandler = (v: any, eventData: ContainerChangeEventData) => emit('change', v, eventData);
|
const changeHandler = (v: any, eventData: ContainerChangeEventData) => emit('change', v, eventData);
|
||||||
|
|||||||
59
packages/form/src/containers/FlexLayout.vue
Normal file
59
packages/form/src/containers/FlexLayout.vue
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<template>
|
||||||
|
<div class="m-form-flex-layout" :style="{ display: 'flex', flexWrap: 'wrap', gap }">
|
||||||
|
<Container
|
||||||
|
v-for="(item, index) in config.items"
|
||||||
|
:key="(item as Record<string, any>)[mForm?.keyProp || '__key'] ?? index"
|
||||||
|
:config="item"
|
||||||
|
:model="name ? model[name] : model"
|
||||||
|
:lastValues="name ? lastValues[name] : lastValues"
|
||||||
|
:is-compare="isCompare"
|
||||||
|
:prop="prop"
|
||||||
|
:size="size"
|
||||||
|
:disabled="disabled"
|
||||||
|
:label-width="config.labelWidth || labelWidth"
|
||||||
|
@change="changeHandler"
|
||||||
|
@addDiffCount="onAddDiffCount()"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, inject } from 'vue';
|
||||||
|
|
||||||
|
import type { FlexLayoutConfig } from '@tmagic/form-schema';
|
||||||
|
|
||||||
|
import type { ContainerChangeEventData, FormState } from '../schema';
|
||||||
|
|
||||||
|
import Container from './Container.vue';
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'MFormFlexLayout',
|
||||||
|
});
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
model: any;
|
||||||
|
lastValues?: any;
|
||||||
|
isCompare?: boolean;
|
||||||
|
config: FlexLayoutConfig;
|
||||||
|
name?: string;
|
||||||
|
labelWidth?: string;
|
||||||
|
prop?: string;
|
||||||
|
size?: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
change: [v: any, eventData: ContainerChangeEventData];
|
||||||
|
addDiffCount: [];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const mForm = inject<FormState | undefined>('mForm');
|
||||||
|
|
||||||
|
const gap = computed(() => props.config.gap || '16px');
|
||||||
|
|
||||||
|
const changeHandler = (v: any, eventData: ContainerChangeEventData) => {
|
||||||
|
emit('change', props.model, eventData);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onAddDiffCount = () => emit('addDiffCount');
|
||||||
|
</script>
|
||||||
26
packages/form/src/containers/FormLabel.vue
Normal file
26
packages/form/src/containers/FormLabel.vue
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<template>
|
||||||
|
<span v-if="tip" style="display: inline-flex; align-items: center">
|
||||||
|
<span v-html="type === 'checkbox' && !useLabel ? '' : text" :title="labelTitle"></span>
|
||||||
|
<TMagicTooltip v-if="tip && (type !== 'checkbox' || useLabel)" placement="top">
|
||||||
|
<TMagicIcon style="margin-left: 5px; display: flex"><warning-filled /></TMagicIcon>
|
||||||
|
<template #content>
|
||||||
|
<div v-html="tip"></div>
|
||||||
|
</template>
|
||||||
|
</TMagicTooltip>
|
||||||
|
</span>
|
||||||
|
<span v-else v-html="type === 'checkbox' && !useLabel ? '' : text" :title="labelTitle"></span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { WarningFilled } from '@element-plus/icons-vue';
|
||||||
|
|
||||||
|
import { TMagicIcon, TMagicTooltip } from '@tmagic/design';
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
tip?: string;
|
||||||
|
type?: string;
|
||||||
|
useLabel?: boolean;
|
||||||
|
text?: string;
|
||||||
|
labelTitle?: string;
|
||||||
|
}>();
|
||||||
|
</script>
|
||||||
@ -2,7 +2,7 @@
|
|||||||
<div class="m-fields-group-list">
|
<div class="m-fields-group-list">
|
||||||
<div v-if="config.extra" v-html="config.extra" style="color: rgba(0, 0, 0, 0.45)"></div>
|
<div v-if="config.extra" v-html="config.extra" style="color: rgba(0, 0, 0, 0.45)"></div>
|
||||||
<div v-if="!model[name] || !model[name].length" class="el-table__empty-block">
|
<div v-if="!model[name] || !model[name].length" class="el-table__empty-block">
|
||||||
<span class="el-table__empty-text">暂无数据</span>
|
<span class="el-table__empty-text t-table__empty">暂无数据</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<MFieldsGroupListItem
|
<MFieldsGroupListItem
|
||||||
@ -26,22 +26,28 @@
|
|||||||
@addDiffCount="onAddDiffCount()"
|
@addDiffCount="onAddDiffCount()"
|
||||||
></MFieldsGroupListItem>
|
></MFieldsGroupListItem>
|
||||||
|
|
||||||
<TMagicButton
|
<div class="m-fields-group-list-footer">
|
||||||
v-if="addable"
|
<TMagicButton v-if="config.enableToggleMode" :icon="Grid" size="small" @click="toggleMode"
|
||||||
type="primary"
|
>切换为表格</TMagicButton
|
||||||
:size="config.enableToggleMode ? 'small' : 'default'"
|
>
|
||||||
:disabled="disabled"
|
<div style="display: flex; justify-content: flex-end; flex: 1">
|
||||||
@click="addHandler"
|
<TMagicButton
|
||||||
>新增</TMagicButton
|
v-if="addable"
|
||||||
>
|
:size="config.enableToggleMode ? 'small' : 'default'"
|
||||||
|
:icon="Plus"
|
||||||
<TMagicButton :icon="Grid" size="small" @click="toggleMode" v-if="config.enableToggleMode">切换为表格</TMagicButton>
|
v-bind="config.addButtonConfig?.props || { type: 'primary' }"
|
||||||
|
:disabled="disabled"
|
||||||
|
@click="addHandler"
|
||||||
|
>{{ config.addButtonConfig?.text || '新增' }}</TMagicButton
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, inject } from 'vue';
|
import { computed, inject } from 'vue';
|
||||||
import { Grid } from '@element-plus/icons-vue';
|
import { Grid, Plus } from '@element-plus/icons-vue';
|
||||||
import { cloneDeep } from 'lodash-es';
|
import { cloneDeep } from 'lodash-es';
|
||||||
|
|
||||||
import { TMagicButton } from '@tmagic/design';
|
import { TMagicButton } from '@tmagic/design';
|
||||||
|
|||||||
@ -1,90 +1,92 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="m-fields-group-list-item">
|
<TMagicCard class="m-fields-group-list-item" :body-style="{ display: expand ? 'block' : 'none' }">
|
||||||
<div>
|
<template #header>
|
||||||
<TMagicButton link :disabled="disabled" @click="expandHandler">
|
<div>
|
||||||
<TMagicIcon><CaretBottom v-if="expand" /><CaretRight v-else /></TMagicIcon>{{ title }}
|
<TMagicButton link :disabled="disabled" @click="expandHandler">
|
||||||
</TMagicButton>
|
<TMagicIcon><CaretBottom v-if="expand" /><CaretRight v-else /></TMagicIcon>{{ title }}
|
||||||
|
</TMagicButton>
|
||||||
|
|
||||||
<TMagicButton
|
|
||||||
v-show="showDelete"
|
|
||||||
type="danger"
|
|
||||||
size="small"
|
|
||||||
link
|
|
||||||
:icon="Delete"
|
|
||||||
:disabled="disabled"
|
|
||||||
@click="removeHandler"
|
|
||||||
></TMagicButton>
|
|
||||||
|
|
||||||
<TMagicButton
|
|
||||||
v-if="copyable"
|
|
||||||
link
|
|
||||||
size="small"
|
|
||||||
type="primary"
|
|
||||||
:icon="DocumentCopy"
|
|
||||||
:disabled="disabled"
|
|
||||||
@click="copyHandler"
|
|
||||||
>复制</TMagicButton
|
|
||||||
>
|
|
||||||
|
|
||||||
<template v-if="movable">
|
|
||||||
<TMagicButton
|
<TMagicButton
|
||||||
v-show="index !== 0"
|
v-show="showDelete"
|
||||||
|
type="danger"
|
||||||
|
size="small"
|
||||||
|
link
|
||||||
|
:icon="Delete"
|
||||||
|
:disabled="disabled"
|
||||||
|
@click="removeHandler"
|
||||||
|
></TMagicButton>
|
||||||
|
|
||||||
|
<TMagicButton
|
||||||
|
v-if="copyable"
|
||||||
link
|
link
|
||||||
size="small"
|
size="small"
|
||||||
|
type="primary"
|
||||||
|
:icon="DocumentCopy"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
:icon="CaretTop"
|
@click="copyHandler"
|
||||||
@click="changeOrder(-1)"
|
>复制</TMagicButton
|
||||||
>上移</TMagicButton
|
|
||||||
>
|
>
|
||||||
<TMagicButton
|
|
||||||
v-show="index !== length - 1"
|
|
||||||
link
|
|
||||||
size="small"
|
|
||||||
:disabled="disabled"
|
|
||||||
:icon="CaretBottom"
|
|
||||||
@click="changeOrder(1)"
|
|
||||||
>下移</TMagicButton
|
|
||||||
>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<TMagicPopover
|
<template v-if="movable">
|
||||||
v-if="config.moveSpecifyLocation"
|
|
||||||
trigger="click"
|
|
||||||
placement="top"
|
|
||||||
width="200"
|
|
||||||
:visible="moveSpecifyLocationVisible"
|
|
||||||
>
|
|
||||||
<template #reference>
|
|
||||||
<TMagicButton
|
<TMagicButton
|
||||||
|
v-show="index !== 0"
|
||||||
link
|
link
|
||||||
size="small"
|
size="small"
|
||||||
type="primary"
|
|
||||||
:icon="Position"
|
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
@click="moveSpecifyLocationVisible = true"
|
:icon="CaretTop"
|
||||||
>移动至</TMagicButton
|
@click="changeOrder(-1)"
|
||||||
|
>上移</TMagicButton
|
||||||
|
>
|
||||||
|
<TMagicButton
|
||||||
|
v-show="index !== length - 1"
|
||||||
|
link
|
||||||
|
size="small"
|
||||||
|
:disabled="disabled"
|
||||||
|
:icon="CaretBottom"
|
||||||
|
@click="changeOrder(1)"
|
||||||
|
>下移</TMagicButton
|
||||||
>
|
>
|
||||||
</template>
|
</template>
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
第<TMagicInputNumber
|
|
||||||
style="margin: 0 5px"
|
|
||||||
v-model="moveSpecifyLocationIndex"
|
|
||||||
size="small"
|
|
||||||
:min="1"
|
|
||||||
:disabled="disabled"
|
|
||||||
></TMagicInputNumber
|
|
||||||
>行
|
|
||||||
</div>
|
|
||||||
<div style="text-align: right; margin-top: 20px">
|
|
||||||
<TMagicButton size="small" text @click="moveSpecifyLocationVisible = false">取消</TMagicButton>
|
|
||||||
<TMagicButton size="small" type="primary" @click="moveSpecifyLocationHandler">确认</TMagicButton>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</TMagicPopover>
|
|
||||||
|
|
||||||
<span v-if="itemExtra" v-html="itemExtra" class="m-form-tip"></span>
|
<TMagicPopover
|
||||||
</div>
|
v-if="config.moveSpecifyLocation"
|
||||||
|
trigger="click"
|
||||||
|
placement="top"
|
||||||
|
width="200"
|
||||||
|
:visible="moveSpecifyLocationVisible"
|
||||||
|
>
|
||||||
|
<template #reference>
|
||||||
|
<TMagicButton
|
||||||
|
link
|
||||||
|
size="small"
|
||||||
|
type="primary"
|
||||||
|
:icon="Position"
|
||||||
|
:disabled="disabled"
|
||||||
|
@click="moveSpecifyLocationVisible = true"
|
||||||
|
>移动至</TMagicButton
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
第<TMagicInputNumber
|
||||||
|
style="margin: 0 5px"
|
||||||
|
v-model="moveSpecifyLocationIndex"
|
||||||
|
size="small"
|
||||||
|
:min="1"
|
||||||
|
:disabled="disabled"
|
||||||
|
></TMagicInputNumber
|
||||||
|
>行
|
||||||
|
</div>
|
||||||
|
<div style="text-align: right; margin-top: 20px">
|
||||||
|
<TMagicButton size="small" text @click="moveSpecifyLocationVisible = false">取消</TMagicButton>
|
||||||
|
<TMagicButton size="small" type="primary" @click="moveSpecifyLocationHandler">确认</TMagicButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</TMagicPopover>
|
||||||
|
|
||||||
|
<span v-if="itemExtra" v-html="itemExtra" class="m-form-tip"></span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
<Container
|
<Container
|
||||||
v-if="expand"
|
v-if="expand"
|
||||||
@ -99,14 +101,14 @@
|
|||||||
@change="changeHandler"
|
@change="changeHandler"
|
||||||
@addDiffCount="onAddDiffCount()"
|
@addDiffCount="onAddDiffCount()"
|
||||||
></Container>
|
></Container>
|
||||||
</div>
|
</TMagicCard>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, inject, ref } from 'vue';
|
import { computed, inject, ref } from 'vue';
|
||||||
import { CaretBottom, CaretRight, CaretTop, Delete, DocumentCopy, Position } from '@element-plus/icons-vue';
|
import { CaretBottom, CaretRight, CaretTop, Delete, DocumentCopy, Position } from '@element-plus/icons-vue';
|
||||||
|
|
||||||
import { TMagicButton, TMagicIcon, TMagicInputNumber, TMagicPopover } from '@tmagic/design';
|
import { TMagicButton, TMagicCard, TMagicIcon, TMagicInputNumber, TMagicPopover } from '@tmagic/design';
|
||||||
|
|
||||||
import type { ContainerChangeEventData, FormState, GroupListConfig } from '../schema';
|
import type { ContainerChangeEventData, FormState, GroupListConfig } from '../schema';
|
||||||
import { filterFunction } from '../utils/form';
|
import { filterFunction } from '../utils/form';
|
||||||
|
|||||||
@ -8,8 +8,11 @@
|
|||||||
<div style="width: 100%; display: flex; align-items: center">
|
<div style="width: 100%; display: flex; align-items: center">
|
||||||
<TMagicButton style="padding: 0" link :icon="expand ? CaretBottom : CaretRight" @click="expand = !expand">
|
<TMagicButton style="padding: 0" link :icon="expand ? CaretBottom : CaretRight" @click="expand = !expand">
|
||||||
</TMagicButton>
|
</TMagicButton>
|
||||||
|
<slot name="header">
|
||||||
|
<span style="cursor: pointer" @click="expand = !expand">{{ filter(config.title) }}</span>
|
||||||
|
</slot>
|
||||||
|
|
||||||
<span v-if="config && config.extra" v-html="config.extra" class="m-form-tip"></span>
|
<span v-if="config && config.extra" v-html="config.extra" class="m-form-tip"></span>
|
||||||
<slot name="header">{{ filter(config.title) }}</slot>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -101,4 +104,12 @@ const changeHandler = (v: any, eventData: ContainerChangeEventData) => {
|
|||||||
emit('change', props.model, eventData);
|
emit('change', props.model, eventData);
|
||||||
};
|
};
|
||||||
const onAddDiffCount = () => emit('addDiffCount');
|
const onAddDiffCount = () => emit('addDiffCount');
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
getExpand: () => expand.value,
|
||||||
|
|
||||||
|
setExpand: (v: boolean) => {
|
||||||
|
expand.value = v;
|
||||||
|
},
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -1,681 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="m-fields-table-wrap">
|
|
||||||
<teleport to="body" :disabled="!isFullscreen">
|
|
||||||
<div ref="mTable" class="m-fields-table" :class="{ 'm-fields-table-item-extra': config.itemExtra }">
|
|
||||||
<span v-if="config.extra" style="color: rgba(0, 0, 0, 0.45)" v-html="config.extra"></span>
|
|
||||||
<TMagicTooltip content="拖拽可排序" placement="left-start" :disabled="config.dropSort !== true">
|
|
||||||
<TMagicTable
|
|
||||||
v-if="model[modelName]"
|
|
||||||
ref="tMagicTable"
|
|
||||||
style="width: 100%"
|
|
||||||
:row-key="config.rowKey || 'id'"
|
|
||||||
:data="data"
|
|
||||||
:lastData="lastData"
|
|
||||||
:border="config.border"
|
|
||||||
:max-height="config.maxHeight"
|
|
||||||
:default-expand-all="true"
|
|
||||||
:key="updateKey"
|
|
||||||
@select="selectHandle"
|
|
||||||
@sort-change="sortChange"
|
|
||||||
>
|
|
||||||
<TMagicTableColumn v-if="config.itemExtra && !config.dropSort" :fixed="'left'" width="30" type="expand">
|
|
||||||
<template v-slot="scope">
|
|
||||||
<span v-html="itemExtra(config.itemExtra, scope.$index)" class="m-form-tip"></span>
|
|
||||||
</template>
|
|
||||||
</TMagicTableColumn>
|
|
||||||
|
|
||||||
<TMagicTableColumn
|
|
||||||
label="操作"
|
|
||||||
:width="config.operateColWidth || 100"
|
|
||||||
align="center"
|
|
||||||
:fixed="config.fixed === false ? undefined : 'left'"
|
|
||||||
>
|
|
||||||
<template v-slot="scope">
|
|
||||||
<slot name="operateCol" :scope="scope"></slot>
|
|
||||||
<TMagicButton
|
|
||||||
v-show="showDelete(scope.$index + 1 + pagecontext * pagesize - 1)"
|
|
||||||
size="small"
|
|
||||||
type="danger"
|
|
||||||
link
|
|
||||||
title="删除"
|
|
||||||
:icon="Delete"
|
|
||||||
@click="removeHandler(scope.$index + 1 + pagecontext * pagesize - 1)"
|
|
||||||
></TMagicButton>
|
|
||||||
|
|
||||||
<TMagicButton
|
|
||||||
v-if="copyable(scope.$index + 1 + pagecontext * pagesize - 1)"
|
|
||||||
link
|
|
||||||
size="small"
|
|
||||||
type="primary"
|
|
||||||
title="复制"
|
|
||||||
:icon="DocumentCopy"
|
|
||||||
:disabled="disabled"
|
|
||||||
@click="copyHandler(scope.$index + 1 + pagecontext * pagesize - 1)"
|
|
||||||
></TMagicButton>
|
|
||||||
</template>
|
|
||||||
</TMagicTableColumn>
|
|
||||||
|
|
||||||
<TMagicTableColumn v-if="sort && model[modelName] && model[modelName].length > 1" label="排序" width="60">
|
|
||||||
<template v-slot="scope">
|
|
||||||
<TMagicTooltip
|
|
||||||
v-if="scope.$index + 1 + pagecontext * pagesize - 1 !== 0"
|
|
||||||
content="点击上移,双击置顶"
|
|
||||||
placement="top"
|
|
||||||
>
|
|
||||||
<TMagicButton
|
|
||||||
plain
|
|
||||||
size="small"
|
|
||||||
type="primary"
|
|
||||||
:icon="ArrowUp"
|
|
||||||
:disabled="disabled"
|
|
||||||
link
|
|
||||||
@click="upHandler(scope.$index + 1 + pagecontext * pagesize - 1)"
|
|
||||||
@dblclick="topHandler(scope.$index + 1 + pagecontext * pagesize - 1)"
|
|
||||||
></TMagicButton>
|
|
||||||
</TMagicTooltip>
|
|
||||||
<TMagicTooltip
|
|
||||||
v-if="scope.$index + 1 + pagecontext * pagesize - 1 !== model[modelName].length - 1"
|
|
||||||
content="点击下移,双击置底"
|
|
||||||
placement="top"
|
|
||||||
>
|
|
||||||
<TMagicButton
|
|
||||||
plain
|
|
||||||
size="small"
|
|
||||||
type="primary"
|
|
||||||
:icon="ArrowDown"
|
|
||||||
:disabled="disabled"
|
|
||||||
link
|
|
||||||
@click="downHandler(scope.$index + 1 + pagecontext * pagesize - 1)"
|
|
||||||
@dblclick="bottomHandler(scope.$index + 1 + pagecontext * pagesize - 1)"
|
|
||||||
></TMagicButton>
|
|
||||||
</TMagicTooltip>
|
|
||||||
</template>
|
|
||||||
</TMagicTableColumn>
|
|
||||||
|
|
||||||
<TMagicTableColumn
|
|
||||||
v-if="selection"
|
|
||||||
align="center"
|
|
||||||
header-align="center"
|
|
||||||
type="selection"
|
|
||||||
width="45"
|
|
||||||
></TMagicTableColumn>
|
|
||||||
|
|
||||||
<TMagicTableColumn width="60" label="序号" v-if="showIndex && config.showIndex">
|
|
||||||
<template v-slot="scope">{{ scope.$index + 1 + pagecontext * pagesize }}</template>
|
|
||||||
</TMagicTableColumn>
|
|
||||||
|
|
||||||
<template v-for="(column, index) in config.items">
|
|
||||||
<TMagicTableColumn
|
|
||||||
v-if="column.type !== 'hidden' && display(column.display)"
|
|
||||||
:prop="column.name"
|
|
||||||
:width="column.width"
|
|
||||||
:label="column.label"
|
|
||||||
:sortable="column.sortable"
|
|
||||||
:sort-orders="['ascending', 'descending']"
|
|
||||||
:key="column[mForm?.keyProp || '__key'] ?? index"
|
|
||||||
:class-name="config.dropSort === true ? 'el-table__column--dropable' : ''"
|
|
||||||
>
|
|
||||||
<template #default="scope">
|
|
||||||
<Container
|
|
||||||
v-if="scope.$index > -1"
|
|
||||||
labelWidth="0"
|
|
||||||
:disabled="disabled"
|
|
||||||
:prop="getProp(scope.$index)"
|
|
||||||
:rules="column.rules"
|
|
||||||
:config="makeConfig(column, scope.row)"
|
|
||||||
:model="scope.row"
|
|
||||||
:lastValues="lastData[scope.$index]"
|
|
||||||
:is-compare="isCompare"
|
|
||||||
:size="size"
|
|
||||||
@change="changeHandler"
|
|
||||||
@addDiffCount="onAddDiffCount()"
|
|
||||||
></Container>
|
|
||||||
</template>
|
|
||||||
</TMagicTableColumn>
|
|
||||||
</template>
|
|
||||||
</TMagicTable>
|
|
||||||
</TMagicTooltip>
|
|
||||||
<slot></slot>
|
|
||||||
|
|
||||||
<div style="display: flex; justify-content: space-between; margin: 10px 0">
|
|
||||||
<TMagicButton v-if="addable" size="small" type="primary" :disabled="disabled" plain @click="newHandler()"
|
|
||||||
>新增一行</TMagicButton
|
|
||||||
>
|
|
||||||
|
|
||||||
<div style="display: flex">
|
|
||||||
<TMagicButton
|
|
||||||
:icon="Grid"
|
|
||||||
size="small"
|
|
||||||
type="primary"
|
|
||||||
@click="toggleMode"
|
|
||||||
v-if="enableToggleMode && config.enableToggleMode !== false && !isFullscreen"
|
|
||||||
>展开配置</TMagicButton
|
|
||||||
>
|
|
||||||
<TMagicButton
|
|
||||||
:icon="FullScreen"
|
|
||||||
size="small"
|
|
||||||
type="primary"
|
|
||||||
@click="toggleFullscreen"
|
|
||||||
v-if="config.enableFullscreen !== false"
|
|
||||||
>
|
|
||||||
{{ isFullscreen ? '退出全屏' : '全屏编辑' }}
|
|
||||||
</TMagicButton>
|
|
||||||
<TMagicUpload
|
|
||||||
v-if="importable"
|
|
||||||
style="display: inline-block"
|
|
||||||
ref="excelBtn"
|
|
||||||
action="/noop"
|
|
||||||
:disabled="disabled"
|
|
||||||
:on-change="excelHandler"
|
|
||||||
:auto-upload="false"
|
|
||||||
>
|
|
||||||
<TMagicButton size="small" type="success" :disabled="disabled" plain>导入EXCEL</TMagicButton>
|
|
||||||
</TMagicUpload>
|
|
||||||
<TMagicButton
|
|
||||||
v-if="importable"
|
|
||||||
size="small"
|
|
||||||
type="warning"
|
|
||||||
:disabled="disabled"
|
|
||||||
plain
|
|
||||||
@click="clearHandler()"
|
|
||||||
>清空</TMagicButton
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="bottom" style="text-align: right" v-if="config.pagination">
|
|
||||||
<TMagicPagination
|
|
||||||
layout="total, sizes, prev, pager, next, jumper"
|
|
||||||
:hide-on-single-page="model[modelName].length < pagesize"
|
|
||||||
:current-page="pagecontext + 1"
|
|
||||||
:page-sizes="[pagesize, 60, 120, 300]"
|
|
||||||
:page-size="pagesize"
|
|
||||||
:total="model[modelName].length"
|
|
||||||
@size-change="handleSizeChange"
|
|
||||||
@current-change="handleCurrentChange"
|
|
||||||
>
|
|
||||||
</TMagicPagination>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</teleport>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { computed, inject, onMounted, ref, toRefs, watchEffect } from 'vue';
|
|
||||||
import { ArrowDown, ArrowUp, Delete, DocumentCopy, FullScreen, Grid } from '@element-plus/icons-vue';
|
|
||||||
import { cloneDeep } from 'lodash-es';
|
|
||||||
import Sortable, { SortableEvent } from 'sortablejs';
|
|
||||||
|
|
||||||
import {
|
|
||||||
TMagicButton,
|
|
||||||
tMagicMessage,
|
|
||||||
TMagicPagination,
|
|
||||||
TMagicTable,
|
|
||||||
TMagicTableColumn,
|
|
||||||
TMagicTooltip,
|
|
||||||
TMagicUpload,
|
|
||||||
useZIndex,
|
|
||||||
} from '@tmagic/design';
|
|
||||||
import { asyncLoadJs } from '@tmagic/utils';
|
|
||||||
|
|
||||||
import type { ContainerChangeEventData, FormState, SortProp, TableColumnConfig, TableConfig } from '../schema';
|
|
||||||
import { display as displayFunc, initValue } from '../utils/form';
|
|
||||||
|
|
||||||
import Container from './Container.vue';
|
|
||||||
|
|
||||||
defineOptions({
|
|
||||||
name: 'MFormTable',
|
|
||||||
});
|
|
||||||
|
|
||||||
const props = withDefaults(
|
|
||||||
defineProps<{
|
|
||||||
model: any;
|
|
||||||
lastValues?: any;
|
|
||||||
isCompare?: boolean;
|
|
||||||
config: TableConfig;
|
|
||||||
name: string;
|
|
||||||
prop?: string;
|
|
||||||
labelWidth?: string;
|
|
||||||
sort?: boolean;
|
|
||||||
disabled?: boolean;
|
|
||||||
sortKey?: string;
|
|
||||||
text?: string;
|
|
||||||
size?: string;
|
|
||||||
enableToggleMode?: boolean;
|
|
||||||
showIndex?: boolean;
|
|
||||||
}>(),
|
|
||||||
{
|
|
||||||
prop: '',
|
|
||||||
sortKey: '',
|
|
||||||
enableToggleMode: true,
|
|
||||||
showIndex: true,
|
|
||||||
lastValues: () => ({}),
|
|
||||||
isCompare: false,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const emit = defineEmits(['change', 'select', 'addDiffCount']);
|
|
||||||
|
|
||||||
let timer: any | null = null;
|
|
||||||
const mForm = inject<FormState | undefined>('mForm');
|
|
||||||
|
|
||||||
const { nextZIndex } = useZIndex();
|
|
||||||
|
|
||||||
const tMagicTable = ref<InstanceType<typeof TMagicTable>>();
|
|
||||||
const excelBtn = ref<InstanceType<typeof TMagicUpload>>();
|
|
||||||
const mTable = ref<HTMLDivElement>();
|
|
||||||
|
|
||||||
const pagesize = ref(10);
|
|
||||||
const pagecontext = ref(0);
|
|
||||||
const updateKey = ref(1);
|
|
||||||
const isFullscreen = ref(false);
|
|
||||||
|
|
||||||
const modelName = computed(() => props.name || props.config.name || '');
|
|
||||||
|
|
||||||
const getDataByPage = (data: any[] = []) =>
|
|
||||||
data.filter(
|
|
||||||
(item: any, index: number) =>
|
|
||||||
index >= pagecontext.value * pagesize.value && index + 1 <= (pagecontext.value + 1) * pagesize.value,
|
|
||||||
);
|
|
||||||
|
|
||||||
const pageinationData = computed(() => getDataByPage(props.model[modelName.value]));
|
|
||||||
|
|
||||||
const data = computed(() => (props.config.pagination ? pageinationData.value : props.model[modelName.value]));
|
|
||||||
|
|
||||||
const lastData = computed(() =>
|
|
||||||
props.config.pagination ? getDataByPage(props.lastValues[modelName.value]) : props.lastValues[modelName.value] || [],
|
|
||||||
);
|
|
||||||
|
|
||||||
const sortChange = ({ prop, order }: SortProp) => {
|
|
||||||
if (order === 'ascending') {
|
|
||||||
props.model[modelName.value] = props.model[modelName.value].sort((a: any, b: any) => a[prop] - b[prop]);
|
|
||||||
} else if (order === 'descending') {
|
|
||||||
props.model[modelName.value] = props.model[modelName.value].sort((a: any, b: any) => b[prop] - a[prop]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const swapArray = (index1: number, index2: number) => {
|
|
||||||
props.model[modelName.value].splice(index1, 0, props.model[modelName.value].splice(index2, 1)[0]);
|
|
||||||
|
|
||||||
if (props.sortKey) {
|
|
||||||
for (let i = props.model[modelName.value].length - 1, v = 0; i >= 0; i--, v++) {
|
|
||||||
props.model[modelName.value][v][props.sortKey] = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mForm?.$emit('field-change', props.prop, props.model[modelName.value]);
|
|
||||||
};
|
|
||||||
|
|
||||||
let sortable: Sortable | undefined;
|
|
||||||
const rowDrop = () => {
|
|
||||||
sortable?.destroy();
|
|
||||||
const tableEl = tMagicTable.value?.instance.$el;
|
|
||||||
const tBodyEl = tableEl?.querySelector('.el-table__body > tbody');
|
|
||||||
if (!tBodyEl) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sortable = Sortable.create(tBodyEl, {
|
|
||||||
draggable: '.tmagic-design-table-row',
|
|
||||||
filter: 'input', // 表单组件选字操作和触发拖拽会冲突,优先保证选字操作
|
|
||||||
preventOnFilter: false, // 允许选字
|
|
||||||
direction: 'vertical',
|
|
||||||
onEnd: ({ newIndex, oldIndex }: SortableEvent) => {
|
|
||||||
if (typeof newIndex === 'undefined') return;
|
|
||||||
if (typeof oldIndex === 'undefined') return;
|
|
||||||
swapArray(newIndex, oldIndex);
|
|
||||||
emit('change', props.model[modelName.value]);
|
|
||||||
mForm?.$emit('field-change', props.prop, props.model[modelName.value]);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const newHandler = async (row?: any) => {
|
|
||||||
if (props.config.max && props.model[modelName.value].length >= props.config.max) {
|
|
||||||
tMagicMessage.error(`最多新增配置不能超过${props.config.max}条`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof props.config.beforeAddRow === 'function') {
|
|
||||||
const beforeCheckRes = props.config.beforeAddRow(mForm, {
|
|
||||||
model: props.model[modelName.value],
|
|
||||||
formValue: mForm?.values,
|
|
||||||
prop: props.prop,
|
|
||||||
});
|
|
||||||
if (!beforeCheckRes) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const columns = props.config.items;
|
|
||||||
const enumValues = props.config.enum || [];
|
|
||||||
let enumV = [];
|
|
||||||
const { length } = props.model[modelName.value];
|
|
||||||
const key = props.config.key || 'id';
|
|
||||||
let inputs: any = {};
|
|
||||||
|
|
||||||
if (enumValues.length) {
|
|
||||||
if (length >= enumValues.length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
enumV = enumValues.filter((item) => {
|
|
||||||
let i = 0;
|
|
||||||
for (; i < length; i++) {
|
|
||||||
if (item[key] === props.model[modelName.value][i][key]) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return i === length;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (enumV.length > 0) {
|
|
||||||
// eslint-disable-next-line prefer-destructuring
|
|
||||||
inputs = enumV[0];
|
|
||||||
}
|
|
||||||
} else if (Array.isArray(row)) {
|
|
||||||
columns.forEach((column, index) => {
|
|
||||||
column.name && (inputs[column.name] = row[index]);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
if (typeof props.config.defaultAdd === 'function') {
|
|
||||||
inputs = await props.config.defaultAdd(mForm, {
|
|
||||||
model: props.model[modelName.value],
|
|
||||||
formValue: mForm?.values,
|
|
||||||
});
|
|
||||||
} else if (props.config.defaultAdd) {
|
|
||||||
inputs = props.config.defaultAdd;
|
|
||||||
}
|
|
||||||
|
|
||||||
inputs = await initValue(mForm, {
|
|
||||||
config: columns,
|
|
||||||
initValues: inputs,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (props.sortKey && length) {
|
|
||||||
inputs[props.sortKey] = props.model[modelName.value][length - 1][props.sortKey] - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
props.model[modelName.value].push(inputs);
|
|
||||||
|
|
||||||
emit('change', props.model[modelName.value], {
|
|
||||||
changeRecords: [
|
|
||||||
{
|
|
||||||
propPath: `${props.prop}.${props.model[modelName.value].length - 1}`,
|
|
||||||
value: inputs,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
if (props.config.defautSort) {
|
|
||||||
sortChange(props.config.defautSort);
|
|
||||||
} else if (props.config.defaultSort) {
|
|
||||||
sortChange(props.config.defaultSort);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (props.sort && props.sortKey) {
|
|
||||||
props.model[modelName.value].sort((a: any, b: any) => b[props.sortKey] - a[props.sortKey]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
watchEffect(() => {
|
|
||||||
if (props.config.dropSort) {
|
|
||||||
rowDrop();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const addable = computed(() => {
|
|
||||||
if (!props.model[modelName.value].length) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (typeof props.config.addable === 'function') {
|
|
||||||
return props.config.addable(mForm, {
|
|
||||||
model: props.model[modelName.value],
|
|
||||||
formValue: mForm?.values,
|
|
||||||
prop: props.prop,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return typeof props.config.addable === 'undefined' ? true : props.config.addable;
|
|
||||||
});
|
|
||||||
|
|
||||||
const selection = computed(() => {
|
|
||||||
if (typeof props.config.selection === 'function') {
|
|
||||||
return props.config.selection(mForm, { model: props.model[modelName.value] });
|
|
||||||
}
|
|
||||||
return props.config.selection;
|
|
||||||
});
|
|
||||||
|
|
||||||
const importable = computed(() => {
|
|
||||||
if (typeof props.config.importable === 'function') {
|
|
||||||
return props.config.importable(mForm, {
|
|
||||||
formValue: mForm?.values,
|
|
||||||
model: props.model[modelName.value],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return typeof props.config.importable === 'undefined' ? false : props.config.importable;
|
|
||||||
});
|
|
||||||
|
|
||||||
const display = (fuc: any) => displayFunc(mForm, fuc, props);
|
|
||||||
|
|
||||||
const itemExtra = (fuc: any, index: number) => {
|
|
||||||
if (typeof fuc === 'function') {
|
|
||||||
return fuc(mForm, {
|
|
||||||
values: mForm?.initValues,
|
|
||||||
model: props.model,
|
|
||||||
formValue: mForm ? mForm.values : props.model,
|
|
||||||
prop: props.prop,
|
|
||||||
index,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return fuc;
|
|
||||||
};
|
|
||||||
|
|
||||||
const removeHandler = (index: number) => {
|
|
||||||
if (props.disabled) return;
|
|
||||||
props.model[modelName.value].splice(index, 1);
|
|
||||||
emit('change', props.model[modelName.value]);
|
|
||||||
};
|
|
||||||
|
|
||||||
const selectHandle = (selection: any, row: any) => {
|
|
||||||
if (typeof props.config.selection === 'string' && props.config.selection === 'single') {
|
|
||||||
tMagicTable.value?.clearSelection();
|
|
||||||
tMagicTable.value?.toggleRowSelection(row, true);
|
|
||||||
}
|
|
||||||
emit('select', selection, row);
|
|
||||||
if (typeof props.config.onSelect === 'function') {
|
|
||||||
props.config.onSelect(mForm, { selection, row, config: props.config });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const toggleRowSelection = (row: any, selected: boolean) => {
|
|
||||||
tMagicTable.value?.toggleRowSelection.call(tMagicTable.value, row, selected);
|
|
||||||
};
|
|
||||||
|
|
||||||
const makeConfig = (config: TableColumnConfig, row: any) => {
|
|
||||||
const newConfig = cloneDeep(config);
|
|
||||||
if (typeof config.itemsFunction === 'function') {
|
|
||||||
newConfig.items = config.itemsFunction(row);
|
|
||||||
}
|
|
||||||
delete newConfig.display;
|
|
||||||
return newConfig;
|
|
||||||
};
|
|
||||||
|
|
||||||
const upHandler = (index: number) => {
|
|
||||||
if (timer) {
|
|
||||||
clearTimeout(timer);
|
|
||||||
}
|
|
||||||
|
|
||||||
timer = setTimeout(() => {
|
|
||||||
swapArray(index, index - 1);
|
|
||||||
timer = undefined;
|
|
||||||
}, 300);
|
|
||||||
};
|
|
||||||
|
|
||||||
const topHandler = (index: number) => {
|
|
||||||
if (timer) {
|
|
||||||
clearTimeout(timer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 首先判断当前元素需要上移几个位置,置底移动到数组的第一位
|
|
||||||
const moveNum = index;
|
|
||||||
|
|
||||||
// 循环出需要一个一个上移的次数
|
|
||||||
for (let i = 0; i < moveNum; i++) {
|
|
||||||
swapArray(index, index - 1);
|
|
||||||
index -= 1;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const downHandler = (index: number) => {
|
|
||||||
if (timer) {
|
|
||||||
clearTimeout(timer);
|
|
||||||
}
|
|
||||||
|
|
||||||
timer = setTimeout(() => {
|
|
||||||
swapArray(index, index + 1);
|
|
||||||
timer = undefined;
|
|
||||||
}, 300);
|
|
||||||
};
|
|
||||||
|
|
||||||
const bottomHandler = (index: number) => {
|
|
||||||
if (timer) {
|
|
||||||
clearTimeout(timer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 首先判断当前元素需要上移几个位置,置底移动到数组的第一位
|
|
||||||
const moveNum = props.model[modelName.value].length - 1 - index;
|
|
||||||
|
|
||||||
// 循环出需要一个一个上移的次数
|
|
||||||
for (let i = 0; i < moveNum; i++) {
|
|
||||||
swapArray(index, index + 1);
|
|
||||||
index += 1;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 希望支持单行可控制是否显示删除按钮,不会影响现有逻辑
|
|
||||||
const showDelete = (index: number) => {
|
|
||||||
const deleteFunc = props.config.delete;
|
|
||||||
if (deleteFunc && typeof deleteFunc === 'function') {
|
|
||||||
return deleteFunc(props.model[modelName.value], index, mForm?.values);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const copyable = (index: number) => {
|
|
||||||
const copyableFunc = props.config.copyable;
|
|
||||||
if (copyableFunc && typeof copyableFunc === 'function') {
|
|
||||||
return copyableFunc(mForm, {
|
|
||||||
values: mForm?.initValues || {},
|
|
||||||
model: props.model,
|
|
||||||
parent: mForm?.parentValues || {},
|
|
||||||
formValue: mForm?.values || props.model,
|
|
||||||
prop: props.prop,
|
|
||||||
config: props.config,
|
|
||||||
index,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const clearHandler = () => {
|
|
||||||
const len = props.model[modelName.value].length;
|
|
||||||
props.model[modelName.value].splice(0, len);
|
|
||||||
mForm?.$emit('field-change', props.prop, props.model[modelName.value]);
|
|
||||||
};
|
|
||||||
|
|
||||||
const excelHandler = async (file: any) => {
|
|
||||||
if (!file?.raw) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(globalThis as any).XLSX) {
|
|
||||||
await asyncLoadJs('https://cdn.bootcdn.net/ajax/libs/xlsx/0.17.0/xlsx.full.min.js');
|
|
||||||
}
|
|
||||||
|
|
||||||
const reader = new FileReader();
|
|
||||||
reader.onload = () => {
|
|
||||||
const data = reader.result;
|
|
||||||
const pdata = (globalThis as any).XLSX.read(data, { type: 'array' });
|
|
||||||
pdata.SheetNames.forEach((sheetName: string) => {
|
|
||||||
const arr = (globalThis as any).XLSX.utils.sheet_to_json(pdata.Sheets[sheetName], { header: 1 });
|
|
||||||
if (arr?.[0]) {
|
|
||||||
arr.forEach((row: any) => {
|
|
||||||
newHandler(row);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
setTimeout(() => {
|
|
||||||
excelBtn.value?.clearFiles();
|
|
||||||
}, 300);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
reader.readAsArrayBuffer(file.raw);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSizeChange = (val: number) => {
|
|
||||||
pagesize.value = val;
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleCurrentChange = (val: number) => {
|
|
||||||
pagecontext.value = val - 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
const copyHandler = (index: number) => {
|
|
||||||
props.model[modelName.value].push(cloneDeep(props.model[modelName.value][index]));
|
|
||||||
};
|
|
||||||
|
|
||||||
const toggleMode = () => {
|
|
||||||
const calcLabelWidth = (label: string) => {
|
|
||||||
if (!label) return '0px';
|
|
||||||
const zhLength = label.match(/[^\x00-\xff]/g)?.length || 0;
|
|
||||||
const chLength = label.length - zhLength;
|
|
||||||
return `${Math.max(chLength * 8 + zhLength * 20, 80)}px`;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 切换为groupList的形式
|
|
||||||
props.config.type = 'groupList';
|
|
||||||
props.config.enableToggleMode = true;
|
|
||||||
props.config.tableItems = props.config.items;
|
|
||||||
props.config.items =
|
|
||||||
props.config.groupItems ||
|
|
||||||
props.config.items.map((item: any) => {
|
|
||||||
const text = item.text || item.label;
|
|
||||||
const labelWidth = calcLabelWidth(text);
|
|
||||||
return {
|
|
||||||
...item,
|
|
||||||
text,
|
|
||||||
labelWidth,
|
|
||||||
span: item.span || 12,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const toggleFullscreen = () => {
|
|
||||||
if (!mTable.value) return;
|
|
||||||
|
|
||||||
if (isFullscreen.value) {
|
|
||||||
mTable.value.classList.remove('fixed');
|
|
||||||
isFullscreen.value = false;
|
|
||||||
} else {
|
|
||||||
mTable.value.classList.add('fixed');
|
|
||||||
mTable.value.style.zIndex = `${nextZIndex()}`;
|
|
||||||
isFullscreen.value = true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const getProp = (index: number) => {
|
|
||||||
const { prop } = toRefs(props);
|
|
||||||
return `${prop.value}${prop.value ? '.' : ''}${index + 1 + pagecontext.value * pagesize.value - 1}`;
|
|
||||||
};
|
|
||||||
|
|
||||||
const onAddDiffCount = () => emit('addDiffCount');
|
|
||||||
|
|
||||||
const changeHandler = (v: any, eventData: ContainerChangeEventData) => {
|
|
||||||
emit('change', props.model, eventData);
|
|
||||||
};
|
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
toggleRowSelection,
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
@ -58,7 +58,13 @@
|
|||||||
: lastValues
|
: lastValues
|
||||||
"
|
"
|
||||||
:is-compare="isCompare"
|
:is-compare="isCompare"
|
||||||
:prop="config.dynamic ? `${prop}${prop ? '.' : ''}${String(tabIndex)}` : prop"
|
:prop="
|
||||||
|
config.dynamic
|
||||||
|
? `${prop}${prop ? '.' : ''}${String(tabIndex)}`
|
||||||
|
: tab.name
|
||||||
|
? `${prop}${prop ? '.' : ''}${tab.name}`
|
||||||
|
: prop
|
||||||
|
"
|
||||||
:size="size"
|
:size="size"
|
||||||
:label-width="tab.labelWidth || labelWidth"
|
:label-width="tab.labelWidth || labelWidth"
|
||||||
:expand-more="expandMore"
|
:expand-more="expandMore"
|
||||||
@ -88,6 +94,26 @@ type DiffCount = {
|
|||||||
[tabIndex: number]: number;
|
[tabIndex: number]: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
model: any;
|
||||||
|
lastValues?: any;
|
||||||
|
isCompare?: boolean;
|
||||||
|
config: TabConfig;
|
||||||
|
name: string;
|
||||||
|
size?: string;
|
||||||
|
labelWidth?: string;
|
||||||
|
prop?: string;
|
||||||
|
expandMore?: boolean;
|
||||||
|
disabled?: boolean;
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
lastValues: () => ({}),
|
||||||
|
isCompare: false,
|
||||||
|
prop: '',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
const tabPaneComponent = getDesignConfig('components')?.tabPane;
|
const tabPaneComponent = getDesignConfig('components')?.tabPane;
|
||||||
const tabsComponent = getDesignConfig('components')?.tabs;
|
const tabsComponent = getDesignConfig('components')?.tabs;
|
||||||
|
|
||||||
@ -118,25 +144,6 @@ const tabClick = (mForm: FormState | undefined, tab: any, props: any) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const props = withDefaults(
|
|
||||||
defineProps<{
|
|
||||||
model: any;
|
|
||||||
lastValues?: any;
|
|
||||||
isCompare?: boolean;
|
|
||||||
config: TabConfig;
|
|
||||||
name: string;
|
|
||||||
size?: string;
|
|
||||||
labelWidth?: string;
|
|
||||||
prop?: string;
|
|
||||||
expandMore?: boolean;
|
|
||||||
disabled?: boolean;
|
|
||||||
}>(),
|
|
||||||
{
|
|
||||||
lastValues: () => ({}),
|
|
||||||
isCompare: false,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
change: [v: any, eventData?: ContainerChangeEventData];
|
change: [v: any, eventData?: ContainerChangeEventData];
|
||||||
addDiffCount: [];
|
addDiffCount: [];
|
||||||
@ -167,7 +174,17 @@ watchEffect(() => {
|
|||||||
|
|
||||||
const tabItems = (tab: TabPaneConfig) => (props.config.dynamic ? props.config.items : tab.items);
|
const tabItems = (tab: TabPaneConfig) => (props.config.dynamic ? props.config.items : tab.items);
|
||||||
|
|
||||||
const tabClickHandler = (tab: any) => tabClick(mForm, tab, props);
|
const tabClickHandler = (tab: any) => {
|
||||||
|
if (typeof tab === 'object') {
|
||||||
|
tabClick(mForm, tab, props);
|
||||||
|
} else {
|
||||||
|
let item = tabs.value.find((tab: any) => tab.status === tab);
|
||||||
|
if (!item) {
|
||||||
|
item = tabs.value[tab];
|
||||||
|
}
|
||||||
|
tabClick(mForm, item, props);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const onTabAdd = async () => {
|
const onTabAdd = async () => {
|
||||||
if (!props.name) throw new Error('dynamic tab 必须配置name');
|
if (!props.name) throw new Error('dynamic tab 必须配置name');
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<TMagicCascader
|
<TMagicCascader
|
||||||
v-model="value"
|
:model-value="value"
|
||||||
ref="tMagicCascader"
|
ref="tMagicCascader"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
clearable
|
clearable
|
||||||
@ -15,6 +15,7 @@
|
|||||||
emitPath: config.emitPath ?? true,
|
emitPath: config.emitPath ?? true,
|
||||||
checkStrictly: checkStrictly ?? false,
|
checkStrictly: checkStrictly ?? false,
|
||||||
}"
|
}"
|
||||||
|
@update:model-value="updateModelValueHandler"
|
||||||
@change="changeHandler"
|
@change="changeHandler"
|
||||||
></TMagicCascader>
|
></TMagicCascader>
|
||||||
</template>
|
</template>
|
||||||
@ -51,22 +52,31 @@ const remoteData = ref<any>(null);
|
|||||||
const checkStrictly = computed(() => filterFunction(mForm, props.config.checkStrictly, props));
|
const checkStrictly = computed(() => filterFunction(mForm, props.config.checkStrictly, props));
|
||||||
const valueSeparator = computed(() => filterFunction<string>(mForm, props.config.valueSeparator, props));
|
const valueSeparator = computed(() => filterFunction<string>(mForm, props.config.valueSeparator, props));
|
||||||
|
|
||||||
const value = computed({
|
const value = computed(() => {
|
||||||
get() {
|
if (typeof props.model[props.name] === 'string' && valueSeparator.value) {
|
||||||
if (typeof props.model[props.name] === 'string' && valueSeparator.value) {
|
return props.model[props.name].split(valueSeparator.value);
|
||||||
return props.model[props.name].split(valueSeparator.value);
|
}
|
||||||
}
|
return props.model[props.name];
|
||||||
return props.model[props.name];
|
|
||||||
},
|
|
||||||
set(value) {
|
|
||||||
let result = value;
|
|
||||||
if (valueSeparator.value) {
|
|
||||||
result = value.join(valueSeparator.value);
|
|
||||||
}
|
|
||||||
props.model[props.name] = result;
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const updateModelValueHandler = (value: string[] | number[] | any) => {
|
||||||
|
let result = value;
|
||||||
|
if (valueSeparator.value) {
|
||||||
|
result = value.join(valueSeparator.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof result === 'undefined') {
|
||||||
|
if (Array.isArray(props.model[props.name])) {
|
||||||
|
emit('change', []);
|
||||||
|
} else if (typeof props.model[props.name] === 'string') {
|
||||||
|
emit('change', '');
|
||||||
|
} else if (typeof props.model[props.name] === 'object') {
|
||||||
|
emit('change', null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
emit('change', result);
|
||||||
|
};
|
||||||
|
|
||||||
const setRemoteOptions = async function () {
|
const setRemoteOptions = async function () {
|
||||||
const { config } = props;
|
const { config } = props;
|
||||||
const { option } = config;
|
const { option } = config;
|
||||||
@ -126,6 +136,5 @@ const changeHandler = () => {
|
|||||||
if (!tMagicCascader.value) return;
|
if (!tMagicCascader.value) return;
|
||||||
tMagicCascader.value.setQuery('');
|
tMagicCascader.value.setQuery('');
|
||||||
tMagicCascader.value.setPreviousQuery(null);
|
tMagicCascader.value.setPreviousQuery(null);
|
||||||
emit('change', props.model[props.name]);
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<TMagicCheckbox
|
<TMagicCheckbox
|
||||||
v-model="model[name]"
|
:model-value="model[name]"
|
||||||
:size="size"
|
:size="size"
|
||||||
:trueValue="activeValue"
|
:trueValue="activeValue"
|
||||||
:falseValue="inactiveValue"
|
:falseValue="inactiveValue"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
@change="changeHandler"
|
@update:model-value="changeHandler"
|
||||||
>{{ config.text }}</TMagicCheckbox
|
><template #default v-if="!config.useLabel">{{ config.text }}</template></TMagicCheckbox
|
||||||
>
|
>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<TMagicCheckboxGroup v-model="model[name]" :size="size" :disabled="disabled" @change="changeHandler">
|
<TMagicCheckboxGroup :model-value="model[name]" :size="size" :disabled="disabled" @update:model-value="changeHandler">
|
||||||
<TMagicCheckbox v-for="option in options" :value="option.value" :key="option.value" :disabled="option.disabled"
|
<TMagicCheckbox v-for="option in options" :value="option.value" :key="option.value" :disabled="option.disabled"
|
||||||
>{{ option.text }}
|
>{{ option.text }}
|
||||||
</TMagicCheckbox>
|
</TMagicCheckbox>
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<TMagicColorPicker
|
<TMagicColorPicker
|
||||||
v-model="model[name]"
|
:model-value="model[name]"
|
||||||
:size="size"
|
:size="size"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
:showAlpha="true"
|
:showAlpha="true"
|
||||||
@change="changeHandler"
|
@update:model-value="changeHandler"
|
||||||
></TMagicColorPicker>
|
></TMagicColorPicker>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<TMagicDatePicker
|
<TMagicDatePicker
|
||||||
v-model="model[name]"
|
:model-value="model[name]"
|
||||||
type="date"
|
type="date"
|
||||||
:size="size"
|
:size="size"
|
||||||
:placeholder="config.placeholder"
|
:placeholder="config.placeholder"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
:format="config.format || 'YYYY/MM/DD'"
|
:format="config.format || 'YYYY/MM/DD'"
|
||||||
:value-format="config.valueFormat || 'YYYY/MM/DD'"
|
:value-format="config.valueFormat || 'YYYY/MM/DD'"
|
||||||
@change="changeHandler"
|
@update:model-value="changeHandler"
|
||||||
></TMagicDatePicker>
|
></TMagicDatePicker>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<TMagicDatePicker
|
<TMagicDatePicker
|
||||||
v-model="model[name]"
|
:model-value="model[name]"
|
||||||
popper-class="magic-datetime-picker-popper"
|
popper-class="magic-datetime-picker-popper"
|
||||||
type="datetime"
|
type="datetime"
|
||||||
:size="size"
|
:size="size"
|
||||||
@ -9,7 +9,7 @@
|
|||||||
:format="config.format || 'YYYY/MM/DD HH:mm:ss'"
|
:format="config.format || 'YYYY/MM/DD HH:mm:ss'"
|
||||||
:value-format="config.valueFormat || 'YYYY/MM/DD HH:mm:ss'"
|
:value-format="config.valueFormat || 'YYYY/MM/DD HH:mm:ss'"
|
||||||
:default-time="config.defaultTime"
|
:default-time="config.defaultTime"
|
||||||
@change="changeHandler"
|
@update:model-value="changeHandler"
|
||||||
></TMagicDatePicker>
|
></TMagicDatePicker>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<TMagicDatePicker
|
<TMagicDatePicker
|
||||||
v-model="value"
|
:model-value="value"
|
||||||
type="datetimerange"
|
type="datetimerange"
|
||||||
range-separator="-"
|
range-separator="-"
|
||||||
start-placeholder="开始日期"
|
start-placeholder="开始日期"
|
||||||
@ -9,19 +9,20 @@
|
|||||||
:unlink-panels="true"
|
:unlink-panels="true"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
:default-time="config.defaultTime"
|
:default-time="config.defaultTime"
|
||||||
|
:format="`${config.dateFormat || 'YYYY/MM/DD'} ${config.timeFormat || 'HH:mm:ss'}`"
|
||||||
:value-format="config.valueFormat || 'YYYY/MM/DD HH:mm:ss'"
|
:value-format="config.valueFormat || 'YYYY/MM/DD HH:mm:ss'"
|
||||||
:date-format="config.dateFormat || 'YYYY/MM/DD'"
|
:date-format="config.dateFormat || 'YYYY/MM/DD'"
|
||||||
:time-format="config.timeFormat || 'HH:mm:ss'"
|
:time-format="config.timeFormat || 'HH:mm:ss'"
|
||||||
@change="changeHandler"
|
@update:model-value="changeHandler"
|
||||||
></TMagicDatePicker>
|
></TMagicDatePicker>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, watch } from 'vue';
|
import { onUnmounted, ref, watch } from 'vue';
|
||||||
|
|
||||||
import { TMagicDatePicker } from '@tmagic/design';
|
import { TMagicDatePicker } from '@tmagic/design';
|
||||||
|
|
||||||
import type { DaterangeConfig, FieldProps } from '../schema';
|
import type { ChangeRecord, DaterangeConfig, FieldProps } from '../schema';
|
||||||
import { datetimeFormatter } from '../utils/form';
|
import { datetimeFormatter } from '../utils/form';
|
||||||
import { useAddField } from '../utils/useAddField';
|
import { useAddField } from '../utils/useAddField';
|
||||||
|
|
||||||
@ -40,7 +41,7 @@ const value = ref<(Date | string | undefined)[] | null>([]);
|
|||||||
|
|
||||||
if (props.model !== undefined) {
|
if (props.model !== undefined) {
|
||||||
if (names?.length) {
|
if (names?.length) {
|
||||||
watch(
|
const unWatch = watch(
|
||||||
[() => props.model[names[0]], () => props.model[names[1]]],
|
[() => props.model[names[0]], () => props.model[names[1]]],
|
||||||
([start, end], [preStart, preEnd]) => {
|
([start, end], [preStart, preEnd]) => {
|
||||||
if (!value.value) {
|
if (!value.value) {
|
||||||
@ -56,8 +57,12 @@ if (props.model !== undefined) {
|
|||||||
immediate: true,
|
immediate: true,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
unWatch();
|
||||||
|
});
|
||||||
} else if (props.name && props.model[props.name]) {
|
} else if (props.name && props.model[props.name]) {
|
||||||
watch(
|
const unWatch = watch(
|
||||||
() => props.model[props.name],
|
() => props.model[props.name],
|
||||||
(start, preStart) => {
|
(start, preStart) => {
|
||||||
const format = `${props.config.dateFormat || 'YYYY/MM/DD'} ${props.config.timeFormat || 'HH:mm:ss'}`;
|
const format = `${props.config.dateFormat || 'YYYY/MM/DD'} ${props.config.timeFormat || 'HH:mm:ss'}`;
|
||||||
@ -71,32 +76,41 @@ if (props.model !== undefined) {
|
|||||||
immediate: true,
|
immediate: true,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
onUnmounted(() => {
|
||||||
|
unWatch();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const setValue = (v: Date[] | Date) => {
|
|
||||||
names?.forEach((item, index) => {
|
|
||||||
if (!props.model) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (Array.isArray(v)) {
|
|
||||||
props.model[item] = v[index];
|
|
||||||
} else {
|
|
||||||
props.model[item] = undefined;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const changeHandler = (v: Date[]) => {
|
const changeHandler = (v: Date[]) => {
|
||||||
const value = v || [];
|
const value = v || [];
|
||||||
|
|
||||||
if (props.name) {
|
if (props.name) {
|
||||||
emit('change', value);
|
emit('change', value);
|
||||||
} else {
|
} else {
|
||||||
if (names?.length) {
|
if (props.config.names?.length) {
|
||||||
setValue(value);
|
const newChangeRecords: ChangeRecord[] = [];
|
||||||
|
props.config.names.forEach((item, index) => {
|
||||||
|
if (!props.model) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Array.isArray(v)) {
|
||||||
|
newChangeRecords.push({
|
||||||
|
propPath: props.prop ? `${props.prop}.${item}` : item,
|
||||||
|
value: v[index],
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
newChangeRecords.push({
|
||||||
|
propPath: props.prop ? `${props.prop}.${item}` : item,
|
||||||
|
value: undefined,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
emit('change', props.model, {
|
||||||
|
changeRecords: newChangeRecords,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
emit('change', props.model);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user