CompTree.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. import { TreeToolbars } from "@/modules/editor/objects/Toolbars";
  2. import { css } from "@linaria/core";
  3. import { useReactive } from "@queenjs/use";
  4. import { Tree } from "ant-design-vue";
  5. import { defineComponent } from "vue";
  6. import { string } from "vue-types";
  7. import { useEditor } from "../../../..";
  8. import { DesignComp } from "../../../../objects/DesignTemp/DesignComp";
  9. type TreeItem = {
  10. key: string;
  11. title: string;
  12. value: string;
  13. children: TreeItem[];
  14. };
  15. export const CompTree = defineComponent({
  16. setup() {
  17. const { store, actions, helper, controls } = useEditor();
  18. const { compUICtrl } = controls;
  19. const state = useReactive(() => ({
  20. expandedKeys() {
  21. const comps = helper.getCompTrees(store.currCompId);
  22. return comps.map((comp) => comp.id);
  23. },
  24. treeData() {
  25. const rootComp = helper.findRootComp();
  26. function getCompChildren(ids: string[]): TreeItem[] {
  27. return ids.map((id) => {
  28. const comp = helper.findComp(id) as DesignComp;
  29. return {
  30. key: comp.id,
  31. title:
  32. compUICtrl.state.components.get(comp.compKey)?.name || "未命名",
  33. value: comp.id,
  34. children: getCompChildren(comp.getChildIds()),
  35. };
  36. });
  37. }
  38. return getCompChildren(rootComp?.id ? [rootComp.id] : []);
  39. },
  40. }));
  41. return () => (
  42. <Tree
  43. class={treeStyle}
  44. treeData={state.treeData}
  45. expandedKeys={state.expandedKeys}
  46. selectedKeys={[store.currCompId]}
  47. blockNode={true}
  48. onSelect={(ids) =>
  49. actions.pickComp(
  50. (ids[0] as string) || state.expandedKeys.at(-2) || "root"
  51. )
  52. }
  53. >
  54. {{
  55. title: (data: any) => {
  56. return <CompNode title={data.title} id={data.key} />;
  57. },
  58. }}
  59. </Tree>
  60. );
  61. },
  62. });
  63. const CompNode = defineComponent({
  64. props: {
  65. id: string().isRequired,
  66. title: string().isRequired,
  67. },
  68. setup(props) {
  69. const editor = useEditor();
  70. const comp = editor.helper.findComp(props.id);
  71. return () => {
  72. if (!comp) return;
  73. const compOpts = editor.controls.compUICtrl.state.components.get(
  74. comp.compKey
  75. );
  76. const actions = TreeToolbars[comp.compKey] || TreeToolbars.default;
  77. const thumbnail =
  78. comp.compKey === "Image" ? comp.value.url : compOpts?.thumbnail;
  79. return (
  80. <div class={nodeStyle}>
  81. <img src={thumbnail} />
  82. <span class="flex-1">{props.title}</span>
  83. <span class="space-x-4px">
  84. {actions.map((action) =>
  85. action.getVisible.call(editor, comp) ? (
  86. <action.component
  87. class="p-4px"
  88. key={comp.id}
  89. value={action.getValue?.(comp)}
  90. onClick={(e: MouseEvent) => {
  91. e.stopPropagation();
  92. action.onClick.call(editor, comp);
  93. }}
  94. />
  95. ) : null
  96. )}
  97. </span>
  98. </div>
  99. );
  100. };
  101. },
  102. });
  103. const treeStyle = css`
  104. .ant-tree-switcher {
  105. display: flex;
  106. justify-content: center;
  107. align-items: center;
  108. }
  109. `;
  110. const nodeStyle = css`
  111. display: flex;
  112. align-items: center;
  113. padding: 6px;
  114. @apply rounded;
  115. > img {
  116. width: 24px;
  117. height: 24px;
  118. margin-right: 6px;
  119. object-fit: contain;
  120. }
  121. `;