20260808172837
This commit is contained in:
1 parent
fa510854b4
commit
4fbfea82f2
32 files changed
+517
-16019
No files matched your search
@@ -503,7 +503,7 @@ defineExpose({
|
||||
:no-data-full="noDataFull"
|
||||
:show-overflow="showOverflow"
|
||||
:area-selection="editable"
|
||||
:bordered="'h'"
|
||||
:bordered="false"
|
||||
@area-selection-change="handleAreaSelectionChange"
|
||||
@row-order-change="handleRowOrderChange"
|
||||
>
|
||||
@@ -521,7 +521,14 @@ defineExpose({
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.fms-table,
|
||||
.fms-table {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 1px solid #e8e8f4;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.fms-table__inner {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -539,6 +546,30 @@ defineExpose({
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 边框由纯 CSS solid border 实现(不用 stk-table 的渐变),彻底避免渐变叠加和粗细不一致问题。
|
||||
* stk-table bordered=false — 不做任何边框绘制。
|
||||
* 外层 .fms-table div — 圆角外框(border)。
|
||||
* 单元格 border-bottom — 行列间的横线。
|
||||
* 最后一行 tbody tr — 去掉 border-bottom(避免与 div bottom border 重叠)。
|
||||
*/
|
||||
.fms-table__inner.stk-table {
|
||||
th,
|
||||
td {
|
||||
border-bottom: 1px solid #e8e8f4;
|
||||
}
|
||||
|
||||
// 表头底部用稍粗的线或同色线均可,这里保持一致
|
||||
thead th {
|
||||
border-bottom-color: #e8e8f4;
|
||||
}
|
||||
|
||||
// 最后一行不画底线,由外层 div 的 border-bottom 统一表现
|
||||
.stk-tbody-main tr:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.fms-checkbox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -291,7 +291,6 @@ function refreshTab(key) {
|
||||
|
||||
/* ---- 标签项(浅灰高亮,与侧栏选中语言统一) ---- */
|
||||
.tab-item {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex: none;
|
||||
min-width: 72px;
|
||||
@@ -299,29 +298,34 @@ function refreshTab(key) {
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
border-radius: 8px;
|
||||
background: #f4f4f5;
|
||||
background: #ffffff;
|
||||
color: #71717a;
|
||||
box-shadow:
|
||||
inset 0 0 0 1px #e4e4e7,
|
||||
0 1px 2px rgb(0 0 0 / 6%),
|
||||
0 1px 1px rgb(0 0 0 / 4%);
|
||||
transition:
|
||||
background-color 0.15s ease,
|
||||
color 0.15s ease;
|
||||
|
||||
&:hover {
|
||||
background: #f4f4f5;
|
||||
color: #3f3f46;
|
||||
}
|
||||
|
||||
/* 选中态:纯白凸起药丸(inset 描边 + 轻投影,边缘利落不脏);关闭 X 作为会话标签的强区分信号 */
|
||||
&--active {
|
||||
color: #27272a;
|
||||
font-weight: 500;
|
||||
background: #ffffff;
|
||||
color: #3f3f46;
|
||||
box-shadow:
|
||||
inset 0 0 0 1px #e4e4e7,
|
||||
0 1px 2px rgb(0 0 0 / 6%),
|
||||
0 1px 1px rgb(0 0 0 / 4%);
|
||||
}
|
||||
|
||||
/* 选中态:浅灰高亮,无边框 */
|
||||
&--active {
|
||||
color: #27272a;
|
||||
font-weight: 500;
|
||||
background: #f4f4f5;
|
||||
box-shadow: none;
|
||||
|
||||
&:hover {
|
||||
background: #ffffff;
|
||||
background: #f4f4f5;
|
||||
color: #27272a;
|
||||
}
|
||||
|
||||
@@ -348,7 +352,6 @@ function refreshTab(key) {
|
||||
padding: 0 8px;
|
||||
font-size: 13px;
|
||||
overflow: hidden;
|
||||
transition: padding-right 0.15s ease;
|
||||
|
||||
span {
|
||||
white-space: nowrap;
|
||||
@@ -357,20 +360,17 @@ function refreshTab(key) {
|
||||
}
|
||||
}
|
||||
|
||||
/* 仅可关闭标签预留右侧 X 空间;不可关闭(如工作台)保持对称居中 */
|
||||
/* 有关闭按钮的 tab,缩小右侧 padding */
|
||||
&--closable &__select {
|
||||
padding-right: 24px;
|
||||
padding-right: 4px;
|
||||
}
|
||||
|
||||
&__close {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 2px;
|
||||
bottom: 0;
|
||||
display: grid;
|
||||
flex: none;
|
||||
width: 22px;
|
||||
width: 18px;
|
||||
padding: 0;
|
||||
margin-right: 2px;
|
||||
place-items: center;
|
||||
border-radius: 4px;
|
||||
color: #a1a1aa;
|
||||
|
||||
@@ -42,6 +42,7 @@ const expandedTreeKeys = ref([]);
|
||||
const selectedModuleId = ref(null);
|
||||
const skipLoad = ref(false);
|
||||
const activeTab = ref("basic");
|
||||
const tabItems = computed(() => visibleTabs.value.map((t) => ({ key: t.key, label: t.tab })));
|
||||
const treeSearch = ref("");
|
||||
|
||||
function filterTree(nodes, keyword) {
|
||||
@@ -1165,106 +1166,92 @@ void permissionStore
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 顶部栏:tab 导航 -->
|
||||
<div class="mm-tab-bar">
|
||||
<nav class="mm-tab-nav">
|
||||
<button
|
||||
v-for="tab in visibleTabs"
|
||||
:key="tab.key"
|
||||
type="button"
|
||||
class="mm-tab-nav__item"
|
||||
:class="{ active: activeTab === tab.key }"
|
||||
@click="activeTab = tab.key"
|
||||
>
|
||||
{{ tab.tab }}
|
||||
</button>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<!-- 面板内容 -->
|
||||
<div class="mm-body">
|
||||
<ModuleBasicPanel
|
||||
v-if="activeTab === 'basic'"
|
||||
:module-id="String(selectedModule.b_id)"
|
||||
:data="drafts.module"
|
||||
:parent-name="parentModuleName"
|
||||
:loading="busy"
|
||||
@update="(v) => onUpdate('module', v)"
|
||||
@i18n-saved="onI18nSaved"
|
||||
/>
|
||||
<ModuleFieldsPanel
|
||||
v-else-if="activeTab === 'fields'"
|
||||
:module-id="String(selectedModule.b_id)"
|
||||
:module-code="selectedModule?.b_code || ''"
|
||||
:fields="drafts.fields"
|
||||
:loading="busy"
|
||||
@update="onFieldsUpdate"
|
||||
@i18n-saved="onI18nSaved"
|
||||
@sync-fields="syncFields"
|
||||
/>
|
||||
<ModuleListConfigPanel
|
||||
v-else-if="activeTab === 'list'"
|
||||
:module-id="String(selectedModule.b_id)"
|
||||
:list-config="drafts.listConfig"
|
||||
:edit-config="drafts.editConfig"
|
||||
:query-config="drafts.queryConfig"
|
||||
:fields="drafts.fields"
|
||||
:groups="drafts.groups"
|
||||
:referenced-group-ids="referencedGroupIds"
|
||||
:loading="busy"
|
||||
@update="(v) => onUpdate('listConfig', v)"
|
||||
@groups-saved="onGroupsSaved"
|
||||
@sync-edit="(v) => onUpdate('editConfig', v)"
|
||||
@sync-query="(v) => onUpdate('queryConfig', v)"
|
||||
/>
|
||||
<ModuleEditConfigPanel
|
||||
v-else-if="activeTab === 'edit'"
|
||||
:module-id="String(selectedModule.b_id)"
|
||||
:edit-config="drafts.editConfig"
|
||||
:list-config="drafts.listConfig"
|
||||
:query-config="drafts.queryConfig"
|
||||
:fields="drafts.fields"
|
||||
:groups="drafts.groups"
|
||||
:referenced-group-ids="referencedGroupIds"
|
||||
:loading="busy"
|
||||
@update="(v) => onUpdate('editConfig', v)"
|
||||
@groups-saved="onGroupsSaved"
|
||||
@sync-list="(v) => onUpdate('listConfig', v)"
|
||||
@sync-query="(v) => onUpdate('queryConfig', v)"
|
||||
/>
|
||||
<ModuleQueryConfigPanel
|
||||
v-else-if="activeTab === 'query'"
|
||||
:module-id="String(selectedModule.b_id)"
|
||||
:query-config="drafts.queryConfig"
|
||||
:fields="drafts.fields"
|
||||
:loading="busy"
|
||||
@update="(v) => onUpdate('queryConfig', v)"
|
||||
/>
|
||||
<ModuleAutoCodePanel
|
||||
v-else-if="activeTab === 'auto-code'"
|
||||
:module-id="String(selectedModule.b_id)"
|
||||
:auto-code="drafts.autoCode"
|
||||
:fields="drafts.fields"
|
||||
:loading="busy"
|
||||
@update="onAutoCodeUpdate"
|
||||
/>
|
||||
<ModulePowersPanel
|
||||
v-else-if="activeTab === 'powers'"
|
||||
:module-id="String(selectedModule.b_id)"
|
||||
:module-code="selectedModule?.b_code || ''"
|
||||
:powers="drafts.powers"
|
||||
:loading="busy"
|
||||
@update="(v) => onUpdate('powers', v)"
|
||||
@i18n-saved="onI18nSaved"
|
||||
/>
|
||||
<ModuleI18nPanel
|
||||
v-else-if="activeTab === 'i18n'"
|
||||
:ref="setI18nPanelRef"
|
||||
:module-id="String(selectedModule.b_id)"
|
||||
:i18n-items="i18nItems"
|
||||
:loading="busy"
|
||||
/>
|
||||
</div>
|
||||
<!-- Tab 导航 + 面板 -->
|
||||
<a-tabs v-model:activeKey="activeTab" :items="tabItems" class="mm-tabs">
|
||||
<template #contentRender="{ item }">
|
||||
<ModuleBasicPanel
|
||||
v-if="item.key === 'basic'"
|
||||
:module-id="String(selectedModule.b_id)"
|
||||
:data="drafts.module"
|
||||
:parent-name="parentModuleName"
|
||||
:loading="busy"
|
||||
@update="(v) => onUpdate('module', v)"
|
||||
@i18n-saved="onI18nSaved"
|
||||
/>
|
||||
<ModuleFieldsPanel
|
||||
v-else-if="item.key === 'fields'"
|
||||
:module-id="String(selectedModule.b_id)"
|
||||
:module-code="selectedModule?.b_code || ''"
|
||||
:fields="drafts.fields"
|
||||
:loading="busy"
|
||||
@update="onFieldsUpdate"
|
||||
@i18n-saved="onI18nSaved"
|
||||
@sync-fields="syncFields"
|
||||
/>
|
||||
<ModuleListConfigPanel
|
||||
v-else-if="item.key === 'list'"
|
||||
:module-id="String(selectedModule.b_id)"
|
||||
:list-config="drafts.listConfig"
|
||||
:edit-config="drafts.editConfig"
|
||||
:query-config="drafts.queryConfig"
|
||||
:fields="drafts.fields"
|
||||
:groups="drafts.groups"
|
||||
:referenced-group-ids="referencedGroupIds"
|
||||
:loading="busy"
|
||||
@update="(v) => onUpdate('listConfig', v)"
|
||||
@groups-saved="onGroupsSaved"
|
||||
@sync-edit="(v) => onUpdate('editConfig', v)"
|
||||
@sync-query="(v) => onUpdate('queryConfig', v)"
|
||||
/>
|
||||
<ModuleEditConfigPanel
|
||||
v-else-if="item.key === 'edit'"
|
||||
:module-id="String(selectedModule.b_id)"
|
||||
:edit-config="drafts.editConfig"
|
||||
:list-config="drafts.listConfig"
|
||||
:query-config="drafts.queryConfig"
|
||||
:fields="drafts.fields"
|
||||
:groups="drafts.groups"
|
||||
:referenced-group-ids="referencedGroupIds"
|
||||
:loading="busy"
|
||||
@update="(v) => onUpdate('editConfig', v)"
|
||||
@groups-saved="onGroupsSaved"
|
||||
@sync-list="(v) => onUpdate('listConfig', v)"
|
||||
@sync-query="(v) => onUpdate('queryConfig', v)"
|
||||
/>
|
||||
<ModuleQueryConfigPanel
|
||||
v-else-if="item.key === 'query'"
|
||||
:module-id="String(selectedModule.b_id)"
|
||||
:query-config="drafts.queryConfig"
|
||||
:fields="drafts.fields"
|
||||
:loading="busy"
|
||||
@update="(v) => onUpdate('queryConfig', v)"
|
||||
/>
|
||||
<ModuleAutoCodePanel
|
||||
v-else-if="item.key === 'auto-code'"
|
||||
:module-id="String(selectedModule.b_id)"
|
||||
:auto-code="drafts.autoCode"
|
||||
:fields="drafts.fields"
|
||||
:loading="busy"
|
||||
@update="onAutoCodeUpdate"
|
||||
/>
|
||||
<ModulePowersPanel
|
||||
v-else-if="item.key === 'powers'"
|
||||
:module-id="String(selectedModule.b_id)"
|
||||
:module-code="selectedModule?.b_code || ''"
|
||||
:powers="drafts.powers"
|
||||
:loading="busy"
|
||||
@update="(v) => onUpdate('powers', v)"
|
||||
@i18n-saved="onI18nSaved"
|
||||
/>
|
||||
<ModuleI18nPanel
|
||||
v-else-if="item.key === 'i18n'"
|
||||
:ref="setI18nPanelRef"
|
||||
:module-id="String(selectedModule.b_id)"
|
||||
:i18n-items="i18nItems"
|
||||
:loading="busy"
|
||||
/>
|
||||
</template>
|
||||
</a-tabs>
|
||||
</template>
|
||||
|
||||
<!-- 未选中模块 -->
|
||||
@@ -1354,6 +1341,7 @@ void permissionStore
|
||||
min-height: 0;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
padding: 0 20px;
|
||||
background: var(--fms-surface);
|
||||
}
|
||||
|
||||
@@ -1365,7 +1353,6 @@ void permissionStore
|
||||
justify-content: flex-start;
|
||||
gap: 16px;
|
||||
min-height: 48px;
|
||||
padding: 0 20px;
|
||||
|
||||
&__switches {
|
||||
display: flex;
|
||||
@@ -1375,14 +1362,28 @@ void permissionStore
|
||||
}
|
||||
}
|
||||
|
||||
/* ---- 顶部栏:tab 导航 ---- */
|
||||
.mm-tab-bar {
|
||||
/* ---- antdv a-tabs 容器 ---- */
|
||||
.mm-tabs {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex: none;
|
||||
align-items: center;
|
||||
height: 44px;
|
||||
padding: 0 20px;
|
||||
border-bottom: 1px solid #e4e4e7;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
|
||||
:deep(.ant-tabs-nav) {
|
||||
margin-bottom: 0;
|
||||
flex: none;
|
||||
}
|
||||
|
||||
:deep(.ant-tabs-content) {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
:deep(.ant-tabs-tabpane) {
|
||||
padding-top: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.mm-switch {
|
||||
@@ -1394,73 +1395,6 @@ void permissionStore
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* ---- 自定义 tab 导航 ---- */
|
||||
.mm-tab-nav {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
align-self: stretch;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
overflow-x: auto;
|
||||
scrollbar-width: none;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&__item {
|
||||
display: inline-flex;
|
||||
align-self: stretch;
|
||||
align-items: center;
|
||||
padding: 0 12px;
|
||||
border: 0;
|
||||
border-radius: 6px;
|
||||
background: transparent;
|
||||
color: #71717a;
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
position: relative;
|
||||
transition:
|
||||
background-color 0.15s ease,
|
||||
color 0.15s ease;
|
||||
|
||||
&:hover {
|
||||
background: #f4f4f5;
|
||||
color: #3f3f46;
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: #3f3f46;
|
||||
font-weight: 500;
|
||||
background: transparent;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 12px;
|
||||
right: 12px;
|
||||
bottom: -1px;
|
||||
height: 2px;
|
||||
border-radius: 2px;
|
||||
background: #3f3f46;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: #f4f4f5;
|
||||
color: #3f3f46;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mm-body {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow: hidden;
|
||||
padding: 16px 20px 0;
|
||||
}
|
||||
|
||||
.mm-loading {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
Reference in new issue
Block a user