diff --git a/code/fms/fms-vue/src/components/AutoHeightTable.vue b/code/fms/fms-vue/src/components/AutoHeightTable.vue new file mode 100644 index 00000000..8cda409e --- /dev/null +++ b/code/fms/fms-vue/src/components/AutoHeightTable.vue @@ -0,0 +1,197 @@ + + + + + diff --git a/code/fms/fms-vue/src/styles/main.scss b/code/fms/fms-vue/src/styles/main.scss index 8307d546..ece5e0d6 100644 --- a/code/fms/fms-vue/src/styles/main.scss +++ b/code/fms/fms-vue/src/styles/main.scss @@ -8,6 +8,8 @@ } * { + margin: 0; + padding: 0; box-sizing: border-box; } @@ -20,7 +22,6 @@ body, height: 100%; min-width: 0; min-height: 0; - margin: 0; } body { diff --git a/code/fms/fms-vue/src/views/DashboardView.vue b/code/fms/fms-vue/src/views/DashboardView.vue index 52abdcc7..2575245a 100644 --- a/code/fms/fms-vue/src/views/DashboardView.vue +++ b/code/fms/fms-vue/src/views/DashboardView.vue @@ -1,63 +1,37 @@ @@ -1254,6 +674,7 @@ onBeforeUnmount(() => tableResizeObserver?.disconnect()); border-radius: 6px; background: #fff; } + .module-workspace { display: flex; height: 100%; @@ -1263,271 +684,140 @@ onBeforeUnmount(() => tableResizeObserver?.disconnect()); overflow: hidden; padding: 0 10px 6px; } + .workspace-header { display: flex; + min-height: 56px; flex: 0 0 auto; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; - min-height: 56px; padding: 6px 0; border-bottom: 1px solid #f0f0f0; } -.header-switches { - flex: 0 0 auto; + +.header-switches, +.switch-item, +.title-line, +.header-actions, +.tab-label { display: flex; align-items: center; +} + +.header-switches { + flex: 0 0 auto; gap: 16px; padding: 0 14px; } + .switch-item { - display: flex; - align-items: center; gap: 8px; } + .switch-label { color: #4b5563; font-size: 13px; white-space: nowrap; } -.title-line, -.header-actions, -.tab-label, -.table-toolbar { - display: flex; - align-items: center; - gap: 8px; -} + .title-line { gap: 9px; } + h1 { margin: 0; color: #111827; font-size: 20px; line-height: 1.3; } + .header-actions { flex-wrap: wrap; justify-content: flex-end; gap: 8px; } -.workspace-tabs { - flex: 1 1 auto; - min-height: 0; - overflow: hidden; -} -.directory-editor { - flex: 1 1 auto; - min-height: 0; - overflow: auto; - padding-top: 10px; -} -.directory-form { - max-width: 760px; -} -.directory-grid, -.dialog-grid { - display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: 0 10px; -} -.dialog-switches { - display: flex; - gap: 20px; -} + .tab-label { gap: 6px; } -.basic-form { - max-width: 1040px; - padding-top: 2px; -} -.form-grid { - display: grid; - grid-template-columns: repeat(3, minmax(0, 1fr)); - gap: 0 10px; -} -.table-pane { - display: flex; - height: 100%; - min-height: 0; - flex-direction: column; - overflow: hidden; -} -.table-body-wrap { - flex: 1; + +.workspace-tabs { min-height: 0; + flex: 1 1 auto; overflow: hidden; } -.table-toolbar { - flex: 0 0 auto; - justify-content: flex-start; - min-height: 40px; - margin-bottom: 4px; -} -.translation-table { - flex: 1 1 auto; - min-height: 0; - overflow: auto; - border: 1px solid #e5e7eb; - border-radius: 6px; -} -.translation-head, -.translation-row { - display: grid; - grid-template-columns: minmax(220px, 1.3fr) repeat(3, minmax(160px, 1fr)); - gap: 12px; - align-items: center; - min-width: 800px; - padding: 7px 10px; -} -.translation-head { - position: sticky; - z-index: 1; - top: 0; - background: #f9fafb; - color: #4b5563; - font-size: 12px; - font-weight: 600; -} -.translation-row { - border-top: 1px solid #f0f0f0; -} -.translation-row code { - overflow: hidden; - color: #374151; - font-size: 12px; - text-overflow: ellipsis; -} -.translation-row { - cursor: pointer; -} -.translation-row--editing, -:deep(.editing-row > td) { - background: #f0f7ff !important; -} -.translation-value { - overflow: hidden; - color: #4b5563; - font-size: 12px; - text-overflow: ellipsis; - white-space: nowrap; -} -.field-name-editor, -.cell-name { - display: flex; - align-items: center; - gap: 4px; -} -.field-name-editor .ant-input { - min-width: 0; -} -.i18n-button { - flex: 0 0 auto; - padding-inline: 5px; -} -.cell-name svg { - flex: 0 0 auto; - color: #8c8c8c; -} -.cell-code { - color: #475569; - font-family: Consolas, monospace; - font-size: 12px; -} :deep(.ant-spin-nested-loading), :deep(.ant-spin-container) { height: 100%; min-height: 0; } + +:deep(.module-workspace > .ant-spin) { + display: flex; + width: 100%; + height: 100%; + min-height: 0; + flex: 1 1 auto; + flex-direction: column; + overflow: hidden; +} + +:deep(.module-workspace > .ant-spin > .ant-spin-container), :deep(.module-workspace > .ant-spin-nested-loading > .ant-spin-container) { display: flex; - flex-direction: column; -} -:deep(.workspace-tabs > .ant-tabs-body-holder) { - flex: 1 1 auto; + height: 100%; min-height: 0; + flex: 1 1 auto; + flex-direction: column; + overflow: hidden; } + +:deep(.workspace-tabs > .ant-tabs-body-holder) { + min-height: 0; + flex: 1 1 auto; +} + :deep(.workspace-tabs > .ant-tabs-body-holder > .ant-tabs-body), :deep(.workspace-tabs > .ant-tabs-body-holder > .ant-tabs-body > .ant-tabs-content), :deep(.workspace-tabs .ant-tabs-tabpane) { height: 100%; min-height: 0; } + :deep(.workspace-tabs .ant-tabs-tabpane) { - overflow: auto; -} -:deep(.workspace-tabs .ant-tabs-tabpane:has(.table-pane)), -:deep(.workspace-tabs .ant-tabs-tabpane:has(.translation-table)) { + display: flex; + flex-direction: column; overflow: hidden; } + :deep(.workspace-tabs > .ant-tabs-nav) { flex: 0 0 auto; margin-bottom: 4px; } -:deep(.table-body-wrap .ant-table-wrapper), -:deep(.table-body-wrap .ant-table), -:deep(.table-body-wrap .ant-table-container) { - height: 100%; - min-height: 0; -} -:deep(.table-body-wrap .ant-table-container) { - display: flex; - flex-direction: column; -} -:deep(.table-body-wrap .ant-table-header) { - flex: 0 0 auto; -} -:deep(.table-body-wrap .ant-table-body) { - flex: 1 1 auto; - height: var(--table-body-height); - min-height: var(--table-body-height); - overflow-y: auto !important; -} -:deep(.basic-form .ant-form-item) { - margin-bottom: 8px; -} -:deep(.directory-form .ant-form-item), -:deep(.directory-dialog-form .ant-form-item) { - margin-bottom: 10px; -} -:deep(.ant-table-row) { - cursor: pointer; -} -:deep(.ant-table-cell .ant-input-number), -:deep(.ant-table-cell .ant-select) { - width: 100%; -} + @media (max-width: 980px) { .module-management { grid-template-columns: 220px minmax(0, 1fr); } + .workspace-header { align-items: flex-start; flex-direction: column; padding-block: 8px; } - .form-grid { - grid-template-columns: repeat(2, minmax(0, 1fr)); - } } + @media (max-width: 720px) { .module-management { grid-template-rows: 180px minmax(0, 1fr); grid-template-columns: 1fr; } + .module-workspace { padding: 0 8px 8px; } - .form-grid { - grid-template-columns: 1fr; - } - .directory-grid, - .dialog-grid { - grid-template-columns: 1fr; - } } diff --git a/code/fms/fms-vue/src/views/module-management/components/ModuleBasicInfoPanel.vue b/code/fms/fms-vue/src/views/module-management/components/ModuleBasicInfoPanel.vue new file mode 100644 index 00000000..d3cdf8c6 --- /dev/null +++ b/code/fms/fms-vue/src/views/module-management/components/ModuleBasicInfoPanel.vue @@ -0,0 +1,143 @@ + + + + + diff --git a/code/fms/fms-vue/src/views/module-management/components/ModuleFieldDefinitionPanel.vue b/code/fms/fms-vue/src/views/module-management/components/ModuleFieldDefinitionPanel.vue new file mode 100644 index 00000000..aa3e645a --- /dev/null +++ b/code/fms/fms-vue/src/views/module-management/components/ModuleFieldDefinitionPanel.vue @@ -0,0 +1,248 @@ + + + + + diff --git a/code/fms/fms-vue/src/views/module-management/components/ModulePowerPanel.vue b/code/fms/fms-vue/src/views/module-management/components/ModulePowerPanel.vue new file mode 100644 index 00000000..177aa9be --- /dev/null +++ b/code/fms/fms-vue/src/views/module-management/components/ModulePowerPanel.vue @@ -0,0 +1,156 @@ + + + + + diff --git a/code/fms/fms-vue/src/views/module-management/components/ModuleTranslationsPanel.vue b/code/fms/fms-vue/src/views/module-management/components/ModuleTranslationsPanel.vue new file mode 100644 index 00000000..eb1b0efd --- /dev/null +++ b/code/fms/fms-vue/src/views/module-management/components/ModuleTranslationsPanel.vue @@ -0,0 +1,140 @@ + + + + + diff --git a/code/fms/fms-vue/src/views/module-management/components/ModuleTreePanel.vue b/code/fms/fms-vue/src/views/module-management/components/ModuleTreePanel.vue index 837be50b..a2210c93 100644 --- a/code/fms/fms-vue/src/views/module-management/components/ModuleTreePanel.vue +++ b/code/fms/fms-vue/src/views/module-management/components/ModuleTreePanel.vue @@ -1,22 +1,17 @@ @@ -113,45 +124,34 @@ function onSelect(keys) { background: #fff; padding: 10px 8px; } + header, -header > div, -.tree-title { +header > div { display: flex; align-items: center; } + header { justify-content: space-between; } + header > div { gap: 8px; } + header span { color: #8c8c8c; font-size: 12px; } -.tree-header-actions { - gap: 4px; -} -.tree-title { - min-width: 0; - gap: 7px; -} -.tree-title span { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} -.tree-title small { - margin-left: auto; - color: #9ca3af; - font-size: 10px; -} -:deep(.ant-spin-nested-loading) { + +.tree-spin { min-height: 0; - flex: 1; + flex: 1 1 auto; overflow: auto; } -:deep(.ant-tree) { - background: transparent; + +:deep(.ant-spin-nested-loading), +:deep(.ant-spin-container) { + min-height: 0; }