From aa837051777e716a968b567f2391762917026597 Mon Sep 17 00:00:00 2001
From: zhf <1204297681@qq.com>
Date: Wed, 25 Sep 2024 21:08:33 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E8=A7=86=E5=9B=BE=E8=AE=BE=E8=AE=A1?=
=?UTF-8?q?=E5=B7=A5=E5=85=B7=E8=A1=A5=E5=85=85=E5=B7=A6=E4=BE=A7=E7=B4=A0?=
=?UTF-8?q?=E6=9D=90=E5=8C=BA?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../public/assets/svg/er-artifacts.svg | 20 ++
.../public/assets/svg/er-entity-list.svg | 24 ++
.../public/assets/svg/tab-container.svg | 11 +
packages/view-design/src/components/index.ts | 17 ++
.../view-design-collapse-control.scss | 30 ++
.../view-design-collapse-control.tsx | 42 +++
.../view-design-collapse-list.scss | 30 ++
.../view-design-collapse-list.tsx | 42 +++
.../view-design-material-page.scss | 148 +++++++++
.../view-design-material-page.tsx | 287 ++++++++++++++++++
.../view-design-structure-tree.scss | 35 +++
.../view-design-structure-tree.tsx | 87 ++++++
packages/view-design/src/global.ts | 7 +
packages/view-design/src/index.ts | 4 +
packages/view-design/src/panel-items/index.ts | 10 +
.../view-design-material-tab/index.ts | 17 ++
.../view-design-material-tab.controller.ts | 174 +++++++++++
.../view-design-material-tab.provider.ts | 21 ++
.../view-design-material-tab.scss | 159 ++++++++++
.../view-design-material-tab.state.ts | 39 +++
.../view-design-material-tab.tsx | 242 +++++++++++++++
.../view-design-material-tree/index.ts | 15 +
...w-design-material-tree.controller.state.ts | 30 ++
.../view-design-material-tree.controller.ts | 73 +++++
.../view-design-material-tree.provider.ts | 21 ++
.../view-design-material-tree.scss | 12 +
.../view-design-material-tree.tsx | 73 +++++
27 files changed, 1670 insertions(+)
create mode 100644 packages/view-design/public/assets/svg/er-artifacts.svg
create mode 100644 packages/view-design/public/assets/svg/er-entity-list.svg
create mode 100644 packages/view-design/public/assets/svg/tab-container.svg
create mode 100644 packages/view-design/src/components/index.ts
create mode 100644 packages/view-design/src/components/view-design-collapse-control/view-design-collapse-control.scss
create mode 100644 packages/view-design/src/components/view-design-collapse-control/view-design-collapse-control.tsx
create mode 100644 packages/view-design/src/components/view-design-collapse-list/view-design-collapse-list.scss
create mode 100644 packages/view-design/src/components/view-design-collapse-list/view-design-collapse-list.tsx
create mode 100644 packages/view-design/src/components/view-design-material-page/view-design-material-page.scss
create mode 100644 packages/view-design/src/components/view-design-material-page/view-design-material-page.tsx
create mode 100644 packages/view-design/src/components/view-design-structure-tree/view-design-structure-tree.scss
create mode 100644 packages/view-design/src/components/view-design-structure-tree/view-design-structure-tree.tsx
create mode 100644 packages/view-design/src/global.ts
create mode 100644 packages/view-design/src/panel-items/index.ts
create mode 100644 packages/view-design/src/panel-items/view-design-material-tab/index.ts
create mode 100644 packages/view-design/src/panel-items/view-design-material-tab/view-design-material-tab.controller.ts
create mode 100644 packages/view-design/src/panel-items/view-design-material-tab/view-design-material-tab.provider.ts
create mode 100644 packages/view-design/src/panel-items/view-design-material-tab/view-design-material-tab.scss
create mode 100644 packages/view-design/src/panel-items/view-design-material-tab/view-design-material-tab.state.ts
create mode 100644 packages/view-design/src/panel-items/view-design-material-tab/view-design-material-tab.tsx
create mode 100644 packages/view-design/src/panel-items/view-design-material-tree/index.ts
create mode 100644 packages/view-design/src/panel-items/view-design-material-tree/view-design-material-tree.controller.state.ts
create mode 100644 packages/view-design/src/panel-items/view-design-material-tree/view-design-material-tree.controller.ts
create mode 100644 packages/view-design/src/panel-items/view-design-material-tree/view-design-material-tree.provider.ts
create mode 100644 packages/view-design/src/panel-items/view-design-material-tree/view-design-material-tree.scss
create mode 100644 packages/view-design/src/panel-items/view-design-material-tree/view-design-material-tree.tsx
diff --git a/packages/view-design/public/assets/svg/er-artifacts.svg b/packages/view-design/public/assets/svg/er-artifacts.svg
new file mode 100644
index 00000000..73d6f948
--- /dev/null
+++ b/packages/view-design/public/assets/svg/er-artifacts.svg
@@ -0,0 +1,20 @@
+
+
\ No newline at end of file
diff --git a/packages/view-design/public/assets/svg/er-entity-list.svg b/packages/view-design/public/assets/svg/er-entity-list.svg
new file mode 100644
index 00000000..0794b8cb
--- /dev/null
+++ b/packages/view-design/public/assets/svg/er-entity-list.svg
@@ -0,0 +1,24 @@
+
+
\ No newline at end of file
diff --git a/packages/view-design/public/assets/svg/tab-container.svg b/packages/view-design/public/assets/svg/tab-container.svg
new file mode 100644
index 00000000..8bcf50e8
--- /dev/null
+++ b/packages/view-design/public/assets/svg/tab-container.svg
@@ -0,0 +1,11 @@
+
+
\ No newline at end of file
diff --git a/packages/view-design/src/components/index.ts b/packages/view-design/src/components/index.ts
new file mode 100644
index 00000000..8d9bb06a
--- /dev/null
+++ b/packages/view-design/src/components/index.ts
@@ -0,0 +1,17 @@
+import { App } from 'vue';
+import IBizViewDesignMaterialPage from './view-design-material-page/view-design-material-page';
+import IBizViewDesignStructureTree from './view-design-structure-tree/view-design-structure-tree';
+import IBizViewDesignCollapseList from './view-design-collapse-list/view-design-collapse-list';
+import IBizViewDesignCollapseControl from './view-design-collapse-control/view-design-collapse-control';
+
+export default {
+ install(app: App): void {
+ app.component('IBizViewDesignMaterialPage', IBizViewDesignMaterialPage);
+ app.component('IBizViewDesignStructureTree', IBizViewDesignStructureTree);
+ app.component('IBizViewDesignCollapseList', IBizViewDesignCollapseList);
+ app.component(
+ 'IBizViewDesignCollapseControl',
+ IBizViewDesignCollapseControl,
+ );
+ },
+};
diff --git a/packages/view-design/src/components/view-design-collapse-control/view-design-collapse-control.scss b/packages/view-design/src/components/view-design-collapse-control/view-design-collapse-control.scss
new file mode 100644
index 00000000..d4253077
--- /dev/null
+++ b/packages/view-design/src/components/view-design-collapse-control/view-design-collapse-control.scss
@@ -0,0 +1,30 @@
+/* stylelint-disable no-descending-specificity */
+/* stylelint-disable selector-class-pattern */
+@include b(view-design-collapse-control) {
+ &:not(:last-child) {
+ .el-collapse {
+ border-bottom: none;
+ }
+ }
+
+ .el-collapse {
+ --el-collapse-header-height: 40px;
+ --el-collapse-header-bg-color: transparent;
+ --el-collapse-content-bg-color: #{getCssVar(color, bg, 1)};
+ --el-collapse-header-text-color: #{getCssVar(color, text, 1)};
+ --el-collapse-header-font-size: 12px;
+
+ .el-collapse-item__header {
+ padding: 0 15px;
+ border: none;
+ }
+
+ .el-collapse-item__wrap {
+ border: none;
+ }
+
+ .el-collapse-item__content {
+ padding: 0;
+ }
+ }
+}
diff --git a/packages/view-design/src/components/view-design-collapse-control/view-design-collapse-control.tsx b/packages/view-design/src/components/view-design-collapse-control/view-design-collapse-control.tsx
new file mode 100644
index 00000000..fef6d801
--- /dev/null
+++ b/packages/view-design/src/components/view-design-collapse-control/view-design-collapse-control.tsx
@@ -0,0 +1,42 @@
+import { defineComponent } from 'vue';
+import { useNamespace } from '@ibiz-template/vue3-util';
+import './view-design-collapse-control.scss';
+
+export default defineComponent({
+ name: 'IBizViewDesignCollapseControl',
+ props: {
+ title: {
+ type: String,
+ default: '',
+ },
+ },
+ setup() {
+ const ns = useNamespace('view-design-collapse-control');
+
+ return {
+ ns,
+ };
+ },
+ render() {
+ return (
+
+
+
+ {{
+ title: () => {
+ return (
+
+ );
+ },
+ }}
+
+
+
+ );
+ },
+});
diff --git a/packages/view-design/src/components/view-design-collapse-list/view-design-collapse-list.scss b/packages/view-design/src/components/view-design-collapse-list/view-design-collapse-list.scss
new file mode 100644
index 00000000..633c44e5
--- /dev/null
+++ b/packages/view-design/src/components/view-design-collapse-list/view-design-collapse-list.scss
@@ -0,0 +1,30 @@
+/* stylelint-disable no-descending-specificity */
+/* stylelint-disable selector-class-pattern */
+@include b(view-design-collapse-list) {
+ &:not(:last-child) {
+ .el-collapse {
+ border-bottom: none;
+ }
+ }
+
+ .el-collapse {
+ --el-collapse-header-height: 40px;
+ --el-collapse-header-bg-color: transparent;
+ --el-collapse-content-bg-color: #{getCssVar(color, bg, 1)};
+ --el-collapse-header-text-color: #{getCssVar(color, text, 1)};
+ --el-collapse-header-font-size: 12px;
+
+ .el-collapse-item__header {
+ padding: 0 15px;
+ border: none;
+ }
+
+ .el-collapse-item__wrap {
+ border: none;
+ }
+
+ .el-collapse-item__content {
+ padding: 0;
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/view-design/src/components/view-design-collapse-list/view-design-collapse-list.tsx b/packages/view-design/src/components/view-design-collapse-list/view-design-collapse-list.tsx
new file mode 100644
index 00000000..34cf9476
--- /dev/null
+++ b/packages/view-design/src/components/view-design-collapse-list/view-design-collapse-list.tsx
@@ -0,0 +1,42 @@
+import { defineComponent } from 'vue';
+import { useNamespace } from '@ibiz-template/vue3-util';
+import './view-design-collapse-list.scss';
+
+export default defineComponent({
+ name: 'IBizViewDesignCollapseList',
+ props: {
+ title: {
+ type: String,
+ default: '',
+ },
+ },
+ setup() {
+ const ns = useNamespace('view-design-collapse-list');
+
+ return {
+ ns,
+ };
+ },
+ render() {
+ return (
+
+
+
+ {{
+ title: () => {
+ return (
+
+ );
+ },
+ }}
+
+
+
+ );
+ },
+});
diff --git a/packages/view-design/src/components/view-design-material-page/view-design-material-page.scss b/packages/view-design/src/components/view-design-material-page/view-design-material-page.scss
new file mode 100644
index 00000000..46c1e28b
--- /dev/null
+++ b/packages/view-design/src/components/view-design-material-page/view-design-material-page.scss
@@ -0,0 +1,148 @@
+/* stylelint-disable selector-class-pattern */
+@include b(view-design-material-page) {
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+ background: rgba(var(#{getCssVarName(grey, 0)}), 1);
+
+ @include m(single) {
+ @include b(view-design-material-page-group-item) {
+ width: 100%;
+ }
+ }
+}
+
+@include b(view-design-material-page-header) {
+ display: flex;
+ flex: 0 0 auto;
+ align-items: center;
+ margin: 8px 0;
+}
+
+@include b(view-design-material-page-header-btn-group) {
+ display: flex;
+ flex: 0 0 auto;
+ align-items: center;
+ margin-right: 8px;
+ margin-left: 16px;
+}
+
+@include b(view-design-material-page-header-btn) {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-right: 2px;
+ font-size: 14px;
+ color: getCssVar(color, text, 3);
+ cursor: pointer;
+
+ > svg {
+ width: 1em;
+ height: 1em;
+ fill: currentcolor;
+ }
+
+ @include when(active) {
+ color: getCssVar(color, text, 1);
+ }
+}
+
+@include b(view-design-material-page-header-search-btn) {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 26px;
+ color: getCssVar(color, text, 3);
+ cursor: pointer;
+}
+
+@include b(view-design-material-page-header-search) {
+ flex: 1 1 0;
+ padding-right: 10px;
+
+ > .el-input {
+ --el-input-height: 26px;
+
+ .el-input__inner::placeholder {
+ font-size: 12px;
+ }
+ }
+}
+
+@include b(view-design-material-page-content) {
+ flex: 1 1 0;
+ overflow: auto;
+
+ .el-collapse {
+ --el-collapse-header-height: 28px;
+ --el-collapse-header-bg-color: transparent;
+ --el-collapse-content-bg-color: #{getCssVar(color, bg, 1)};
+ --el-collapse-header-text-color: #{getCssVar(color, text, 1)};
+ --el-collapse-header-font-size: 12px;
+
+ border: none;
+
+ .el-collapse-item__header {
+ border: none;
+ }
+
+ .el-collapse-item__wrap {
+ border: none;
+ }
+
+ .el-collapse-item__content {
+ display: flex;
+ flex-wrap: wrap;
+ padding: 0;
+ }
+ }
+}
+
+@include b(view-design-material-page-group-header) {
+ padding-left: 6px;
+ overflow: hidden;
+ font-size: 12px;
+ color: getCssVar(color, text, 1);
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+@include b(view-design-material-page-group-item) {
+ width: calc(100% / 3);
+ height: 80px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+
+ @include e(icon) {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 56px;
+ height: 56px;
+ margin: 0 auto;
+
+ ion-icon {
+ font-size: 56px;
+ }
+
+ img {
+ max-width: 100%;
+ }
+ }
+
+ @include e(text) {
+ padding: 0 4px;
+ overflow: hidden;
+ line-height: 20px;
+ text-align: center;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+}
+
+@include b(view-design-material-page-group-item-content) {
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+ height: 100%;
+}
diff --git a/packages/view-design/src/components/view-design-material-page/view-design-material-page.tsx b/packages/view-design/src/components/view-design-material-page/view-design-material-page.tsx
new file mode 100644
index 00000000..a6ce3b59
--- /dev/null
+++ b/packages/view-design/src/components/view-design-material-page/view-design-material-page.tsx
@@ -0,0 +1,287 @@
+/* eslint-disable @typescript-eslint/no-explicit-any */
+/* eslint-disable no-return-assign */
+import { PropType, defineComponent, onMounted, ref } from 'vue';
+import { useClickOutside, useNamespace } from '@ibiz-template/vue3-util';
+import { IDEFormGroupPanel } from '@ibiz/model-core';
+import { resource } from '../../global';
+import './view-design-material-page.scss';
+
+export default defineComponent({
+ name: 'IBizViewDesignMaterialPage',
+ props: {
+ groups: {
+ type: Array as PropType,
+ default: () => [],
+ },
+ columnMode: {
+ type: String as PropType<'multiple' | 'single'>,
+ default: 'multiple',
+ },
+ activeGroups: {
+ type: Array as PropType,
+ default: () => [],
+ },
+ },
+ setup(props) {
+ const ns = useNamespace('view-design-material-page');
+
+ // 收缩面板值
+ const collapseValue = ref(props.groups.map(group => group.codeName));
+
+ // 搜索值
+ const searchValue = ref('');
+
+ // 搜索框容器元素
+ const search = ref();
+
+ // 是否展示搜索框
+ const isShowSearch = ref(false);
+
+ onMounted(() => {
+ if (search.value) {
+ useClickOutside(search as any, (): void => {
+ isShowSearch.value = false;
+ });
+ }
+ });
+
+ // 收缩分组
+ const collapse = (): void => {
+ collapseValue.value = [];
+ };
+
+ // 展开分组
+ const expand = (): void => {
+ collapseValue.value = props.groups.map(group => group.codeName);
+ };
+
+ // 渲染图标
+ const renderIcon = (icon?: string): any => {
+ if (icon) {
+ if (icon.startsWith('http')) {
+ return
;
+ }
+ if (icon.endsWith('')) {
+ const svg = URL.createObjectURL(
+ new Blob([icon], { type: 'image/svg+xml;charset=utf-8' }),
+ );
+ return
;
+ }
+ if (icon.startsWith('data:image')) {
+ return
;
+ }
+ }
+ return (
+
+ );
+ };
+
+ return {
+ ns,
+ collapseValue,
+ searchValue,
+ isShowSearch,
+ search,
+ collapse,
+ expand,
+ renderIcon,
+ };
+ },
+ render() {
+ const isExpandAll = this.groups.every(group =>
+ this.collapseValue.includes(group.codeName),
+ );
+ return (
+
+
+
+
+ {this.groups.map(group => {
+ if (!this.activeGroups.includes(group.codeName!)) {
+ return;
+ }
+ return (
+
+ {{
+ title: () => {
+ return (
+
+ );
+ },
+ default: () => {
+ return group.deformDetails?.map(item => {
+ if (this.searchValue) {
+ const regExp = this.searchValue.trim().toLowerCase();
+ const text = item.caption?.toLowerCase();
+ if (text && text.indexOf(regExp) === -1) {
+ return;
+ }
+ }
+ return (
+
+
+
+ {this.renderIcon(item.sysImage?.imagePath)}
+
+
+ {item.caption || ''}
+
+
+
+ );
+ });
+ },
+ }}
+
+ );
+ })}
+
+
+
+ );
+ },
+});
diff --git a/packages/view-design/src/components/view-design-structure-tree/view-design-structure-tree.scss b/packages/view-design/src/components/view-design-structure-tree/view-design-structure-tree.scss
new file mode 100644
index 00000000..02e0dd6d
--- /dev/null
+++ b/packages/view-design/src/components/view-design-structure-tree/view-design-structure-tree.scss
@@ -0,0 +1,35 @@
+/* stylelint-disable selector-class-pattern */
+@include b(view-design-structure-tree) {
+ width: 100%;
+ height: 100%;
+ background: rgba(var(#{getCssVarName(grey, 0)}), 1);
+}
+
+@include b(view-design-structure-tree-search) {
+ padding: 2px 10px 2px 0;
+ margin-left: 8px;
+
+ > .el-input {
+ --el-input-height: 26px;
+
+ .el-input__inner::placeholder {
+ font-size: 12px;
+ }
+ }
+}
+
+@include b(view-design-structure-tree-header) {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 0 12px 0 28px;
+ font-size: 12px;
+ line-height: 28px;
+
+ @include e(action) {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ cursor: pointer;
+ }
+}
diff --git a/packages/view-design/src/components/view-design-structure-tree/view-design-structure-tree.tsx b/packages/view-design/src/components/view-design-structure-tree/view-design-structure-tree.tsx
new file mode 100644
index 00000000..e3e70bb1
--- /dev/null
+++ b/packages/view-design/src/components/view-design-structure-tree/view-design-structure-tree.tsx
@@ -0,0 +1,87 @@
+import { defineComponent, ref } from 'vue';
+import { useNamespace } from '@ibiz-template/vue3-util';
+import './view-design-structure-tree.scss';
+
+export default defineComponent({
+ name: 'IBizViewDesignStructureTree',
+ setup() {
+ const ns = useNamespace('view-design-structure-tree');
+
+ // 搜索值
+ const searchValue = ref('');
+
+ return {
+ ns,
+ searchValue,
+ };
+ },
+ render() {
+ return (
+
+
+
+ {{
+ prefix: () => {
+ return ;
+ },
+ }}
+
+
+
+
+
+
+
+ );
+ },
+});
diff --git a/packages/view-design/src/global.ts b/packages/view-design/src/global.ts
new file mode 100644
index 00000000..0fa10431
--- /dev/null
+++ b/packages/view-design/src/global.ts
@@ -0,0 +1,7 @@
+// 文件路径: [插件项目的根目录]/src/global.ts
+
+import { PluginStaticResource } from '@ibiz-template/runtime';
+
+const resource = new PluginStaticResource(import.meta.url);
+
+export { resource };
diff --git a/packages/view-design/src/index.ts b/packages/view-design/src/index.ts
index b17714e6..a35de149 100644
--- a/packages/view-design/src/index.ts
+++ b/packages/view-design/src/index.ts
@@ -3,10 +3,14 @@
import { App } from 'vue';
import Views from './views';
import Services from './service';
+import PanelItems from './panel-items';
+import Components from './components';
export default {
install(app: App) {
app.use(Views);
app.use(Services);
+ app.use(PanelItems);
+ app.use(Components);
},
};
diff --git a/packages/view-design/src/panel-items/index.ts b/packages/view-design/src/panel-items/index.ts
new file mode 100644
index 00000000..bd679f7c
--- /dev/null
+++ b/packages/view-design/src/panel-items/index.ts
@@ -0,0 +1,10 @@
+import { App } from 'vue';
+import ViewDesignMaterialTree from './view-design-material-tree';
+import ViewDesignMaterialTab from './view-design-material-tab';
+
+export default {
+ install(app: App): void {
+ app.use(ViewDesignMaterialTree);
+ app.use(ViewDesignMaterialTab);
+ },
+};
diff --git a/packages/view-design/src/panel-items/view-design-material-tab/index.ts b/packages/view-design/src/panel-items/view-design-material-tab/index.ts
new file mode 100644
index 00000000..a02be406
--- /dev/null
+++ b/packages/view-design/src/panel-items/view-design-material-tab/index.ts
@@ -0,0 +1,17 @@
+/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
+/* eslint-disable @typescript-eslint/explicit-function-return-type */
+import { App } from 'vue';
+import { registerPanelItemProvider } from '@ibiz-template/runtime';
+import ViewDesignMaterialTab from './view-design-material-tab';
+import { ViewDesignMaterialTabProvider } from './view-design-material-tab.provider';
+
+export default {
+ install(app: App) {
+ // 注册组件
+ app.component('IBizViewDesignMaterialTab', ViewDesignMaterialTab);
+ registerPanelItemProvider(
+ 'RAWITEM_VIEW_DESIGN_MATERIAL_TAB',
+ () => new ViewDesignMaterialTabProvider(),
+ );
+ },
+};
diff --git a/packages/view-design/src/panel-items/view-design-material-tab/view-design-material-tab.controller.ts b/packages/view-design/src/panel-items/view-design-material-tab/view-design-material-tab.controller.ts
new file mode 100644
index 00000000..bc3da886
--- /dev/null
+++ b/packages/view-design/src/panel-items/view-design-material-tab/view-design-material-tab.controller.ts
@@ -0,0 +1,174 @@
+import {
+ PanelItemController,
+ calcLayoutHeightWidth,
+ getControl,
+} from '@ibiz-template/runtime';
+import {
+ IDEEditForm,
+ IDEFormGroupPanel,
+ IDEFormPage,
+ IDEFormTabPanel,
+} from '@ibiz/model-core';
+import { ViewDesignMaterialTabState } from './view-design-material-tab.state';
+import { ViewDesignMaterialTreeController } from '../view-design-material-tree/view-design-material-tree.controller';
+
+export class ViewDesignMaterialTabController extends PanelItemController {
+ declare state: ViewDesignMaterialTabState;
+
+ protected createState(): ViewDesignMaterialTabState {
+ return new ViewDesignMaterialTabState(this.parent?.state);
+ }
+
+ get materialForm(): IDEEditForm {
+ return getControl(this.panel.view.model, 'material') as IDEEditForm;
+ }
+
+ get viewDesignMaterialTree(): ViewDesignMaterialTreeController | undefined {
+ return this.panel.panelItems
+ .view_design_material_tree as ViewDesignMaterialTreeController;
+ }
+
+ protected async onInit(): Promise {
+ await super.onInit();
+ this.initItems();
+ }
+
+ /**
+ * 初始化项数据
+ *
+ * @author zhanghengfeng
+ * @date 2024-09-25 20:09:21
+ * @return {*} {void}
+ */
+ initItems(): void {
+ const formPages = this.materialForm.deformPages;
+ if (!formPages) {
+ return;
+ }
+ const pages: IDEFormPage[] = [];
+ formPages.forEach(formPage => {
+ pages.push(formPage);
+ const details = formPage.deformDetails;
+ details?.forEach(detail => {
+ if (detail.detailType === 'TABPANEL') {
+ const tabPages = (detail as IDEFormTabPanel).deformTabPages;
+ if (tabPages) {
+ pages.push(...tabPages);
+ }
+ }
+ });
+ });
+ const materialPage = pages.find(page => page.codeName === 'controls');
+ if (materialPage) {
+ const details = materialPage.deformDetails;
+ const groups: IDEFormGroupPanel[] = [];
+ details?.forEach(detail => {
+ if (
+ detail.detailType === 'GROUPPANEL' &&
+ detail.codeName?.toUpperCase() !== 'HIDDENGROUP'
+ ) {
+ groups.push(detail);
+ }
+ });
+ this.state.pageItems = formPages?.map(page => {
+ return {
+ id: page.codeName === 'toolkit' ? 'controls' : page.codeName || '',
+ text: page.caption || '',
+ imagePath: page.sysImage?.imagePath,
+ };
+ });
+ this.state.menuItems.push(
+ ...groups.map(group => {
+ return {
+ id: group.codeName || '',
+ text: group.caption || '',
+ };
+ }),
+ );
+ this.state.activeItems.push(...groups.map(group => group.codeName || ''));
+ }
+ }
+
+ /**
+ * 处理选中改变
+ *
+ * @author zhanghengfeng
+ * @date 2024-09-25 20:09:47
+ * @param {string} value
+ * @return {*} {void}
+ */
+ onSelect(value: string): void {
+ if (!this.viewDesignMaterialTree) {
+ return;
+ }
+ if (this.state.pageItems.some(page => page.id === value)) {
+ const parent = this.viewDesignMaterialTree.parent;
+ if (!parent) {
+ return;
+ }
+ const { layoutPos } = parent.model;
+ if (!layoutPos) {
+ return;
+ }
+ const { width } = calcLayoutHeightWidth(layoutPos);
+ parent.state.layout.width = `${width}`;
+ this.state.columnMode = 'multiple';
+ this.viewDesignMaterialTree.state.columnMode = this.state.columnMode;
+ this.viewDesignMaterialTree.state.activePage = value;
+ return;
+ }
+ this.viewDesignMaterialTree.state.activePage = 'controls';
+ if (value === '$multiple' || value === '$single') {
+ const parent = this.viewDesignMaterialTree.parent;
+ if (!parent) {
+ return;
+ }
+ const { layoutPos } = parent.model;
+ if (!layoutPos) {
+ return;
+ }
+ const { width } = calcLayoutHeightWidth(layoutPos);
+ if (value === '$multiple') {
+ parent.state.layout.width = `${width}`;
+ }
+ if (value === '$single') {
+ parent.state.layout.width = `calc(${width} / 3)`;
+ }
+ this.state.columnMode = value.slice(1) as 'multiple' | 'single';
+ this.viewDesignMaterialTree.state.columnMode = this.state.columnMode;
+ return;
+ }
+ if (value === '$component') {
+ this.state.activeItems = [];
+ this.viewDesignMaterialTree.state.activeGroups = [
+ ...this.state.activeItems,
+ ];
+ return;
+ }
+ if (value === '$all') {
+ const result = this.state.menuItems.every(item =>
+ this.state.activeItems.includes(item.id),
+ );
+ if (!result) {
+ this.state.activeItems = this.state.menuItems.map(item => item.id);
+ } else {
+ this.state.activeItems = this.state.menuItems[0]?.id
+ ? [this.state.menuItems[0].id]
+ : [];
+ }
+ this.viewDesignMaterialTree.state.activeGroups = [
+ ...this.state.activeItems,
+ ];
+ return;
+ }
+ const index = this.state.activeItems.findIndex(v => v === value);
+ if (index !== -1) {
+ this.state.activeItems.splice(index, 1);
+ } else {
+ this.state.activeItems.push(value);
+ }
+ this.viewDesignMaterialTree.state.activeGroups = [
+ ...this.state.activeItems,
+ ];
+ }
+}
diff --git a/packages/view-design/src/panel-items/view-design-material-tab/view-design-material-tab.provider.ts b/packages/view-design/src/panel-items/view-design-material-tab/view-design-material-tab.provider.ts
new file mode 100644
index 00000000..fff0daa7
--- /dev/null
+++ b/packages/view-design/src/panel-items/view-design-material-tab/view-design-material-tab.provider.ts
@@ -0,0 +1,21 @@
+import {
+ IPanelItemController,
+ IPanelItemProvider,
+ IPanelController,
+} from '@ibiz-template/runtime';
+import { IPanelItem } from '@ibiz/model-core';
+import { ViewDesignMaterialTabController } from './view-design-material-tab.controller';
+
+export class ViewDesignMaterialTabProvider implements IPanelItemProvider {
+ component = 'IBizViewDesignMaterialTab';
+
+ async createController(
+ panelItem: IPanelItem,
+ panel: IPanelController,
+ parent?: IPanelItemController,
+ ): Promise {
+ const c = new ViewDesignMaterialTabController(panelItem, panel, parent);
+ await c.init();
+ return c;
+ }
+}
diff --git a/packages/view-design/src/panel-items/view-design-material-tab/view-design-material-tab.scss b/packages/view-design/src/panel-items/view-design-material-tab/view-design-material-tab.scss
new file mode 100644
index 00000000..8b2a0e10
--- /dev/null
+++ b/packages/view-design/src/panel-items/view-design-material-tab/view-design-material-tab.scss
@@ -0,0 +1,159 @@
+/* stylelint-disable selector-class-pattern */
+@include b(view-design-material-tab) {
+ display: flex;
+ align-items: center;
+ padding: 0 16px 0 10px;
+
+ .el-menu {
+ --el-menu-hover-text-color: #{getCssVar(color, primary, hover)};
+ --el-menu-hover-bg-color: #{getCssVar(color, primary, light, default)};
+ --el-menu-text-color: #{getCssVar(color, text, 2)};
+
+ &.el-menu--horizontal.el-menu {
+ --el-menu-horizontal-height: 24px;
+ --el-menu-item-height: 24px;
+ --el-menu-icon-width: 20px;
+ --el-menu-base-level-padding: #{getCssVar('spacing', 'tight')};
+
+ border: none;
+
+ @include b(view-design-material-tab-menu-item) {
+ @include m(node) {
+ margin-left: getCssVar('spacing', 'base-loose');
+ border-radius: getCssVar(border, radius, small);
+ }
+ }
+ }
+
+ &.el-menu--horizontal > .el-menu-item {
+ border-bottom: none;
+ }
+
+ &.el-menu--horizontal > .el-menu-item.is-active {
+ border-bottom: none;
+ }
+
+ &.el-menu--horizontal .el-menu-item:not(:hover):focus {
+ background-color: transparent;
+ }
+
+ &.el-menu--horizontal > .el-sub-menu {
+ margin-right: 20px;
+ }
+
+ &.el-menu--horizontal > .el-sub-menu .el-sub-menu__title {
+ color: var(--el-menu-text-color);
+ border: none;
+ border-radius: 4px;
+
+ &:hover {
+ background-color: var(--el-menu-hover-bg-color);
+ }
+ }
+ }
+}
+
+@include b(view-design-material-tab-menu-header) {
+ display: flex;
+ align-items: center;
+
+ @include e(icon) {
+ display: flex;
+ flex: 0 0 auto;
+ align-items: center;
+ justify-content: center;
+ }
+
+ @include e(text) {
+ margin-left: 6px;
+ }
+}
+
+@include b(view-design-material-tab-page-item) {
+ border-radius: 4px;
+
+ @include e(icon) {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-right: 6px;
+ color: var(--el-menu-text-color);
+ }
+
+ @include e(text) {
+ margin-right: 6px;
+ color: var(--el-menu-text-color);
+ }
+}
+
+@include b(view-design-material-tab-sub-menu-header) {
+ display: flex;
+ align-items: center;
+
+ @include e(text) {
+ color: var(--el-menu-text-color);
+ }
+}
+
+@include b(view-design-material-tab-menu-item) {
+ @include e(icon) {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-right: 4px;
+ color: var(--el-menu-text-color);
+ }
+
+ @include e(text) {
+ margin-right: 4px;
+ color: var(--el-menu-text-color);
+ }
+
+ @include e(select-icon) {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-left: auto;
+ visibility: hidden;
+ }
+
+ @include m(active) {
+ color: var(--el-menu-hover-text-color);
+ background-color: var(--el-menu-hover-bg-color);
+
+ @include e(select-icon) {
+ visibility: visible;
+ }
+ }
+}
+
+@include b(view-design-material-tab-popper) {
+ --el-menu-horizontal-sub-item-height: 32px;
+ --el-menu-base-level-padding: #{getCssVar('spacing', 'base-tight')};
+ --el-menu-hover-text-color: #{getCssVar(color, primary, hover)};
+ --el-menu-hover-bg-color: #{getCssVar(color, primary, light, default)};
+ --el-menu-text-color: #{getCssVar(color, text, 2)};
+
+ .el-menu--popup {
+ min-width: 120px;
+ }
+
+ &.el-menu--horizontal .el-menu {
+ @include b(view-design-material-tab-menu-item) {
+ @include m(active) {
+ color: var(--el-menu-hover-text-color);
+ background-color: var(--el-menu-hover-bg-color);
+
+ @include e(select-icon) {
+ visibility: visible;
+ }
+ }
+ }
+ }
+
+ &.el-menu--horizontal .el-menu .el-sub-menu__title {
+ &:hover {
+ background-color: var(--el-menu-hover-bg-color);
+ }
+ }
+}
diff --git a/packages/view-design/src/panel-items/view-design-material-tab/view-design-material-tab.state.ts b/packages/view-design/src/panel-items/view-design-material-tab/view-design-material-tab.state.ts
new file mode 100644
index 00000000..7f41c98d
--- /dev/null
+++ b/packages/view-design/src/panel-items/view-design-material-tab/view-design-material-tab.state.ts
@@ -0,0 +1,39 @@
+import { PanelItemState } from '@ibiz-template/runtime';
+
+export class ViewDesignMaterialTabState extends PanelItemState {
+ /**
+ * 分页项
+ *
+ * @author zhanghengfeng
+ * @date 2024-09-25 20:09:24
+ * @type {{ id: string; text: string; imagePath?: string }[]}
+ */
+ pageItems: { id: string; text: string; imagePath?: string }[] = [];
+
+ /**
+ * 菜单项
+ *
+ * @author zhanghengfeng
+ * @date 2024-09-25 20:09:35
+ * @type {{ id: string; text: string }[]}
+ */
+ menuItems: { id: string; text: string }[] = [];
+
+ /**
+ * 激活菜单项
+ *
+ * @author zhanghengfeng
+ * @date 2024-09-25 20:09:46
+ * @type {string[]}
+ */
+ activeItems: string[] = [];
+
+ /**
+ * 布局模式
+ *
+ * @author zhanghengfeng
+ * @date 2024-09-25 20:09:57
+ * @type {('multiple' | 'single')}
+ */
+ columnMode: 'multiple' | 'single' = 'multiple';
+}
diff --git a/packages/view-design/src/panel-items/view-design-material-tab/view-design-material-tab.tsx b/packages/view-design/src/panel-items/view-design-material-tab/view-design-material-tab.tsx
new file mode 100644
index 00000000..bb5b8a2d
--- /dev/null
+++ b/packages/view-design/src/panel-items/view-design-material-tab/view-design-material-tab.tsx
@@ -0,0 +1,242 @@
+import { PropType, defineComponent } from 'vue';
+import { useNamespace } from '@ibiz-template/vue3-util';
+import { IPanelItem } from '@ibiz/model-core';
+import { ViewDesignMaterialTabController } from './view-design-material-tab.controller';
+import { resource } from '../../global';
+import './view-design-material-tab.scss';
+
+export default defineComponent({
+ name: 'IBizViewDesignMaterialTab',
+ props: {
+ modelData: {
+ type: Object as PropType,
+ required: true,
+ },
+ controller: {
+ type: ViewDesignMaterialTabController,
+ required: true,
+ },
+ },
+ setup() {
+ const ns = useNamespace('view-design-material-tab');
+
+ return {
+ ns,
+ };
+ },
+ render() {
+ const renderSelectIcon = () => (
+
+ );
+ return (
+
+
this.controller.onSelect(value)}
+ >
+ {this.controller.state.pageItems.map(page => {
+ if (page.id === 'controls') {
+ return (
+ {
+ this.controller.onSelect('$multiple');
+ const result = this.controller.state.menuItems.every(item =>
+ this.controller.state.activeItems.includes(item.id),
+ );
+ if (!result) {
+ this.controller.onSelect('$all');
+ }
+ }}
+ >
+ {{
+ title: () => {
+ return (
+
+ );
+ },
+ default: () => {
+ return [
+
+ {{
+ title: () => {
+ return (
+
+ );
+ },
+ default: () => {
+ return [
+
+
+
+
+ {renderSelectIcon()}
+
+ ,
+
+
+
+
+ {renderSelectIcon()}
+
+ ,
+ ];
+ },
+ }}
+ ,
+
+ this.controller.state.activeItems.includes(
+ item.id,
+ ),
+ ) && this.ns.bm('menu-item', 'active'),
+ ]}
+ >
+
+
+ ,
+ this.controller.state.menuItems.map(item => {
+ return (
+
+
+
+
+ );
+ }),
+
+
+
+ ,
+ ];
+ },
+ }}
+
+ );
+ }
+
+ return (
+
+
+
})
+
+ {page.text}
+
+ );
+ })}
+
+
+ );
+ },
+});
diff --git a/packages/view-design/src/panel-items/view-design-material-tree/index.ts b/packages/view-design/src/panel-items/view-design-material-tree/index.ts
new file mode 100644
index 00000000..002c2a8f
--- /dev/null
+++ b/packages/view-design/src/panel-items/view-design-material-tree/index.ts
@@ -0,0 +1,15 @@
+import { App } from 'vue';
+import { registerPanelItemProvider } from '@ibiz-template/runtime';
+import ViewDesignMaterialTree from './view-design-material-tree';
+import { ViewDesignMaterialTreeProvider } from './view-design-material-tree.provider';
+
+export default {
+ install(app: App): void {
+ // 注册组件
+ app.component('IBizViewDesignMaterialTree', ViewDesignMaterialTree);
+ registerPanelItemProvider(
+ 'RAWITEM_VIEW_DESIGN_MATERIAL_TREE',
+ () => new ViewDesignMaterialTreeProvider(),
+ );
+ },
+};
diff --git a/packages/view-design/src/panel-items/view-design-material-tree/view-design-material-tree.controller.state.ts b/packages/view-design/src/panel-items/view-design-material-tree/view-design-material-tree.controller.state.ts
new file mode 100644
index 00000000..61973f5a
--- /dev/null
+++ b/packages/view-design/src/panel-items/view-design-material-tree/view-design-material-tree.controller.state.ts
@@ -0,0 +1,30 @@
+import { PanelItemState } from '@ibiz-template/runtime';
+
+export class ViewDesignMaterialTreeState extends PanelItemState {
+ /**
+ * 布局模式
+ *
+ * @author zhanghengfeng
+ * @date 2024-09-25 20:09:52
+ * @type {('multiple' | 'single')}
+ */
+ columnMode: 'multiple' | 'single' = 'multiple';
+
+ /**
+ * 激活分组
+ *
+ * @author zhanghengfeng
+ * @date 2024-09-25 20:09:02
+ * @type {string[]}
+ */
+ activeGroups: string[] = [];
+
+ /**
+ * 激活分页
+ *
+ * @author zhanghengfeng
+ * @date 2024-09-25 20:09:15
+ * @type {string}
+ */
+ activePage: string = '';
+}
diff --git a/packages/view-design/src/panel-items/view-design-material-tree/view-design-material-tree.controller.ts b/packages/view-design/src/panel-items/view-design-material-tree/view-design-material-tree.controller.ts
new file mode 100644
index 00000000..e748fde8
--- /dev/null
+++ b/packages/view-design/src/panel-items/view-design-material-tree/view-design-material-tree.controller.ts
@@ -0,0 +1,73 @@
+import { PanelItemController, getControl } from '@ibiz-template/runtime';
+import {
+ IDEEditForm,
+ IDEFormGroupPanel,
+ IDEFormPage,
+ IDEFormTabPanel,
+} from '@ibiz/model-core';
+import { clone } from 'ramda';
+import { ViewDesignMaterialTreeState } from './view-design-material-tree.controller.state';
+
+export class ViewDesignMaterialTreeController extends PanelItemController {
+ declare state: ViewDesignMaterialTreeState;
+
+ protected createState(): ViewDesignMaterialTreeState {
+ return new ViewDesignMaterialTreeState(this.parent?.state);
+ }
+
+ get materialForm(): IDEEditForm {
+ return getControl(this.panel.view.model, 'material') as IDEEditForm;
+ }
+
+ /**
+ * 素材分组
+ *
+ * @author zhanghengfeng
+ * @date 2024-09-25 20:09:44
+ * @type {IDEFormGroupPanel[]}
+ */
+ materialGroups: IDEFormGroupPanel[] = [];
+
+ protected async onInit(): Promise {
+ await super.onInit();
+ this.initMaterialGroups();
+ this.state.activeGroups = this.materialGroups.map(group => group.codeName!);
+ }
+
+ /**
+ * 初始化素材分组
+ *
+ * @author zhanghengfeng
+ * @date 2024-09-25 21:09:04
+ */
+ initMaterialGroups(): void {
+ const formPages = this.materialForm.deformPages;
+ const pages: IDEFormPage[] = [];
+ formPages?.forEach(formPage => {
+ pages.push(formPage);
+ const details = formPage.deformDetails;
+ details?.forEach(detail => {
+ if (detail.detailType === 'TABPANEL') {
+ const tabPages = (detail as IDEFormTabPanel).deformTabPages;
+ if (tabPages) {
+ pages.push(...tabPages);
+ }
+ }
+ });
+ });
+ const materialPage = pages.find(page => page.codeName === 'controls');
+ if (materialPage) {
+ const details = materialPage.deformDetails;
+ const groups: IDEFormGroupPanel[] = [];
+ details?.forEach(detail => {
+ if (
+ detail.detailType === 'GROUPPANEL' &&
+ detail.codeName?.toUpperCase() !== 'HIDDENGROUP'
+ ) {
+ groups.push(detail);
+ }
+ });
+ this.materialGroups = clone(groups);
+ }
+ }
+}
diff --git a/packages/view-design/src/panel-items/view-design-material-tree/view-design-material-tree.provider.ts b/packages/view-design/src/panel-items/view-design-material-tree/view-design-material-tree.provider.ts
new file mode 100644
index 00000000..fc839654
--- /dev/null
+++ b/packages/view-design/src/panel-items/view-design-material-tree/view-design-material-tree.provider.ts
@@ -0,0 +1,21 @@
+import {
+ IPanelItemController,
+ IPanelItemProvider,
+ IPanelController,
+} from '@ibiz-template/runtime';
+import { IPanelItem } from '@ibiz/model-core';
+import { ViewDesignMaterialTreeController } from './view-design-material-tree.controller';
+
+export class ViewDesignMaterialTreeProvider implements IPanelItemProvider {
+ component = 'IBizViewDesignMaterialTree';
+
+ async createController(
+ panelItem: IPanelItem,
+ panel: IPanelController,
+ parent?: IPanelItemController,
+ ): Promise {
+ const c = new ViewDesignMaterialTreeController(panelItem, panel, parent);
+ await c.init();
+ return c;
+ }
+}
diff --git a/packages/view-design/src/panel-items/view-design-material-tree/view-design-material-tree.scss b/packages/view-design/src/panel-items/view-design-material-tree/view-design-material-tree.scss
new file mode 100644
index 00000000..fbe6416b
--- /dev/null
+++ b/packages/view-design/src/panel-items/view-design-material-tree/view-design-material-tree.scss
@@ -0,0 +1,12 @@
+@include b(view-design-material-tree) {
+ width: 100%;
+ height: 100%;
+ border: 1px solid getCssVar(color, border);
+}
+
+@include b(view-design-material-tree-caption) {
+ padding: 0 10px;
+ font-size: 18px;
+ line-height: 40px;
+ cursor: pointer;
+}
diff --git a/packages/view-design/src/panel-items/view-design-material-tree/view-design-material-tree.tsx b/packages/view-design/src/panel-items/view-design-material-tree/view-design-material-tree.tsx
new file mode 100644
index 00000000..c1234fd4
--- /dev/null
+++ b/packages/view-design/src/panel-items/view-design-material-tree/view-design-material-tree.tsx
@@ -0,0 +1,73 @@
+import { PropType, defineComponent, ref } from 'vue';
+import { useNamespace } from '@ibiz-template/vue3-util';
+import { IPanelItem } from '@ibiz/model-core';
+import { ViewDesignMaterialTreeController } from './view-design-material-tree.controller';
+import './view-design-material-tree.scss';
+
+export default defineComponent({
+ name: 'IBizViewDesignMaterialTree',
+ props: {
+ modelData: {
+ type: Object as PropType,
+ required: true,
+ },
+ controller: {
+ type: ViewDesignMaterialTreeController,
+ required: true,
+ },
+ },
+ setup() {
+ const ns = useNamespace('view-design-material-tree');
+
+ // 分割值
+ const splitValue = ref(0.5);
+
+ return {
+ ns,
+ splitValue,
+ };
+ },
+ render() {
+ if (this.controller.state.activePage === 'viewdesign') {
+ return (
+
+
+ {{
+ top: () => {
+ return (
+
+ );
+ },
+ bottom: () => {
+ return (
+
+
+ {this.controller.panel.view?.state?.caption || ''}
+
+
+
+
+
+ );
+ },
+ }}
+
+
+ );
+ }
+ return (
+
+
+
+ );
+ },
+});
--
Gitee