feat: 新增预算费控模型与报销审批流引擎
后端新增预算费控服务和报销单审批流模块,引入申请人费用画像 算法,优化知识库 RAG 运行时和同步逻辑,完善报销单工作流常 量和明细同步,更新差旅报销规则电子表格,前端新增预算分析 组件和数字员工模型,完善审批对话框和洞察面板交互,优化侧 边栏和顶栏样式,补充单元测试。
This commit is contained in:
@@ -9,33 +9,52 @@
|
||||
</svg>
|
||||
</div>
|
||||
<strong class="brand-name">{{ displayCompanyName }}</strong>
|
||||
<button
|
||||
class="rail-collapse-btn"
|
||||
type="button"
|
||||
:aria-label="collapsed ? '展开侧边栏' : '折叠侧边栏'"
|
||||
:title="collapsed ? '展开侧边栏' : '折叠侧边栏'"
|
||||
:aria-expanded="!collapsed"
|
||||
@click="emit('toggle-collapse')"
|
||||
<ElTooltip
|
||||
:content="collapseTooltipContent"
|
||||
placement="right"
|
||||
effect="light"
|
||||
:show-after="180"
|
||||
:hide-after="0"
|
||||
:offset="12"
|
||||
popper-class="rail-tooltip-popper"
|
||||
>
|
||||
<i :class="collapsed ? 'mdi mdi-chevron-right' : 'mdi mdi-chevron-left'"></i>
|
||||
</button>
|
||||
<button
|
||||
class="rail-collapse-btn"
|
||||
type="button"
|
||||
:aria-label="collapseTooltipContent"
|
||||
:aria-expanded="!collapsed"
|
||||
@click="emit('toggle-collapse')"
|
||||
>
|
||||
<i :class="collapsed ? 'mdi mdi-chevron-right' : 'mdi mdi-chevron-left'"></i>
|
||||
</button>
|
||||
</ElTooltip>
|
||||
</div>
|
||||
|
||||
<nav class="rail-nav" aria-label="功能导航">
|
||||
<button
|
||||
<ElTooltip
|
||||
v-for="item in decoratedNavItems"
|
||||
:key="item.id"
|
||||
class="nav-btn"
|
||||
:class="{ active: activeView === item.id }"
|
||||
type="button"
|
||||
:title="collapsed ? item.displayLabel : undefined"
|
||||
@click="emit('navigate', item.id)"
|
||||
:content="item.displayLabel"
|
||||
placement="right"
|
||||
effect="light"
|
||||
:disabled="!collapsed"
|
||||
:show-after="180"
|
||||
:hide-after="0"
|
||||
:offset="12"
|
||||
popper-class="rail-tooltip-popper"
|
||||
>
|
||||
<span class="nav-icon" v-html="item.icon"></span>
|
||||
<span class="nav-label">{{ item.displayLabel }}</span>
|
||||
<span v-if="item.hasNewMessage" class="nav-unread-dot" aria-hidden="true"></span>
|
||||
<span v-if="item.badge" class="nav-badge">{{ item.badge }}</span>
|
||||
</button>
|
||||
<button
|
||||
class="nav-btn"
|
||||
:class="{ active: activeView === item.id }"
|
||||
type="button"
|
||||
@click="emit('navigate', item.id)"
|
||||
>
|
||||
<span class="nav-icon" v-html="item.icon"></span>
|
||||
<span class="nav-label">{{ item.displayLabel }}</span>
|
||||
<span v-if="item.hasNewMessage" class="nav-unread-dot" aria-hidden="true"></span>
|
||||
<span v-if="item.badge" class="nav-badge">{{ item.badge }}</span>
|
||||
</button>
|
||||
</ElTooltip>
|
||||
</nav>
|
||||
|
||||
<div
|
||||
@@ -69,19 +88,31 @@
|
||||
</div>
|
||||
</Teleport>
|
||||
|
||||
<div class="user-summary" tabindex="0" aria-label="用户信息" :title="collapsed ? displayUser.name : undefined">
|
||||
<span class="user-avatar">{{ displayUser.avatar }}</span>
|
||||
<span class="user-copy">
|
||||
<strong>{{ displayUser.name }}</strong>
|
||||
<span>{{ displayUser.role }}</span>
|
||||
</span>
|
||||
<i class="mdi mdi-chevron-up"></i>
|
||||
</div>
|
||||
<ElTooltip
|
||||
:content="userTooltipContent"
|
||||
placement="top"
|
||||
effect="light"
|
||||
:disabled="!collapsed"
|
||||
:show-after="180"
|
||||
:hide-after="0"
|
||||
:offset="10"
|
||||
popper-class="rail-tooltip-popper"
|
||||
>
|
||||
<div class="user-summary" tabindex="0" :aria-label="userTooltipContent">
|
||||
<span class="user-avatar">{{ displayUser.avatar }}</span>
|
||||
<span class="user-copy">
|
||||
<strong>{{ displayUser.name }}</strong>
|
||||
<span>{{ displayUser.role }}</span>
|
||||
</span>
|
||||
<i class="mdi mdi-chevron-up"></i>
|
||||
</div>
|
||||
</ElTooltip>
|
||||
</div>
|
||||
</aside>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ElTooltip } from 'element-plus'
|
||||
import { computed, onBeforeUnmount, onMounted, reactive, ref, watch } from 'vue'
|
||||
|
||||
import { useDocumentCenterInbox } from '../../composables/useDocumentCenterInbox.js'
|
||||
@@ -154,6 +185,8 @@ const displayUser = computed(() => ({
|
||||
}))
|
||||
|
||||
const displayCompanyName = computed(() => props.companyName || 'X-Financial')
|
||||
const collapseTooltipContent = computed(() => (props.collapsed ? '展开侧边栏' : '折叠侧边栏'))
|
||||
const userTooltipContent = computed(() => [displayUser.value.name, displayUser.value.role].filter(Boolean).join(' · '))
|
||||
|
||||
const userMenuOpen = ref(false)
|
||||
let userMenuCloseTimer = null
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
class="detail-alert-pill"
|
||||
:class="alert.tone"
|
||||
>
|
||||
<i class="mdi mdi-alert-circle-outline"></i>
|
||||
<i :class="alert.icon || 'mdi mdi-alert-circle-outline'"></i>
|
||||
<span>{{ alert.label }}</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user