feat(web): 统一平台管理员判定与 AI 工作台申请预览动作接入
- authUser 抽出 resolveAuthUserAdminFlag,统一 isAdmin 解析(含 superadmin、role_codes、中英文角色名),accessControl 复用同一逻辑 - 登录态、应用外壳路由、系统状态接入统一管理员判定,LoginView 与相关 composable 配套调整 - AI 工作台申请提交改为调用新的 /application-preview-action 接口,草稿保存仍走 orchestrator;预审模型补充重叠冲突提示与阻断判断 - 同步更新 accessControl/api-request/ai 预览动作等前端测试
This commit is contained in:
@@ -4,8 +4,7 @@
|
||||
:class="{
|
||||
'sidebar-collapsed': sidebarCollapsed,
|
||||
'workbench-ai-sidebar-active': isAiShellMode,
|
||||
'mobile-sidebar-open': mobileSidebarOpen,
|
||||
'login-entry-active': loginEntryAnimating
|
||||
'mobile-sidebar-open': mobileSidebarOpen
|
||||
}"
|
||||
>
|
||||
<div class="mobile-overlay" aria-hidden="true" @click="mobileSidebarOpen = false"></div>
|
||||
@@ -18,17 +17,6 @@
|
||||
>
|
||||
<i class="mdi mdi-menu" aria-hidden="true"></i>
|
||||
</button>
|
||||
<Transition name="login-entry-veil">
|
||||
<div v-if="loginEntryAnimating" class="login-entry-veil" aria-live="polite" aria-label="登录成功,正在进入工作台">
|
||||
<FloatingLightBandWindow
|
||||
icon="mdi mdi-shield-check-outline"
|
||||
message="正在进入工作台"
|
||||
motion="entry"
|
||||
title="登录成功"
|
||||
variant="entry"
|
||||
/>
|
||||
</div>
|
||||
</Transition>
|
||||
<div class="app-sidebar">
|
||||
<Transition name="sidebar-mode-fade" mode="out-in">
|
||||
<AiSidebarRail
|
||||
@@ -169,6 +157,18 @@
|
||||
@request-deleted="handleRequestDeleted"
|
||||
/>
|
||||
|
||||
<section
|
||||
v-else-if="activeView === 'documents' && detailMode && !selectedRequest"
|
||||
class="document-detail-loading panel"
|
||||
aria-live="polite"
|
||||
>
|
||||
<i class="mdi mdi-loading mdi-spin" aria-hidden="true"></i>
|
||||
<div>
|
||||
<strong>正在加载完整单据详情</strong>
|
||||
<p>正在读取申请表、审批进度和详情字段,加载完成后再展示详情表格。</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<DocumentsCenterView
|
||||
v-else-if="activeView === 'documents'"
|
||||
:filtered-requests="requests"
|
||||
@@ -236,13 +236,12 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
||||
import { computed, nextTick, ref, watch } from 'vue'
|
||||
|
||||
import AiSidebarRail from '../components/layout/AiSidebarRail.vue'
|
||||
import SidebarRail from '../components/layout/SidebarRail.vue'
|
||||
import TopBar from '../components/layout/TopBar.vue'
|
||||
import FilterBar from '../components/layout/FilterBar.vue'
|
||||
import FloatingLightBandWindow from '../components/shared/FloatingLightBandWindow.vue'
|
||||
import AuditView from './AuditView.vue'
|
||||
import BudgetCenterView from './BudgetCenterView.vue'
|
||||
import DigitalEmployeesView from './DigitalEmployeesView.vue'
|
||||
@@ -258,9 +257,8 @@ import TravelRequestDetailView from './TravelRequestDetailView.vue'
|
||||
|
||||
import { useAppShell } from '../composables/useAppShell.js'
|
||||
import { useSystemState } from '../composables/useSystemState.js'
|
||||
import { filterNavItemsByAccess } from '../utils/accessControl.js'
|
||||
import { filterNavItemsByAccess, isPlatformAdminUser } from '../utils/accessControl.js'
|
||||
import { loadAiWorkbenchConversationHistory, saveAiWorkbenchConversation } from '../utils/aiWorkbenchConversationStore.js'
|
||||
import { consumeLoginEntryTransition } from '../utils/loginEntryTransition.js'
|
||||
|
||||
const employeeSummary = ref(null)
|
||||
const knowledgeSummary = ref(null)
|
||||
@@ -271,7 +269,6 @@ const auditDetailOpen = ref(false)
|
||||
const digitalEmployeeDetailOpen = ref(false)
|
||||
const receiptFolderDetailOpen = ref(false)
|
||||
const budgetDetailOpen = ref(false)
|
||||
const loginEntryAnimating = ref(false)
|
||||
const sidebarCollapsed = ref(false)
|
||||
const sidebarCollapsedBeforeAiMode = ref(false)
|
||||
const mobileSidebarOpen = ref(false)
|
||||
@@ -281,25 +278,6 @@ const aiSidebarCommandSeq = ref(0)
|
||||
const aiSidebarCommand = ref({ seq: 0, type: '', payload: null })
|
||||
const aiActiveConversationId = ref('')
|
||||
const aiConversationHistory = ref([])
|
||||
let loginEntryTimer = null
|
||||
|
||||
function stopLoginEntryAnimation() {
|
||||
if (loginEntryTimer) {
|
||||
window.clearTimeout(loginEntryTimer)
|
||||
loginEntryTimer = null
|
||||
}
|
||||
|
||||
loginEntryAnimating.value = false
|
||||
}
|
||||
|
||||
function playLoginEntryAnimation() {
|
||||
if (!consumeLoginEntryTransition()) {
|
||||
return
|
||||
}
|
||||
|
||||
loginEntryAnimating.value = true
|
||||
loginEntryTimer = window.setTimeout(stopLoginEntryAnimation, 920)
|
||||
}
|
||||
|
||||
function toggleSidebarCollapsed() {
|
||||
sidebarCollapsed.value = !sidebarCollapsed.value
|
||||
@@ -414,7 +392,7 @@ const resolvedDetailKpis = computed(() => (
|
||||
))
|
||||
|
||||
function openWorkbenchDocument(payload = {}) {
|
||||
const requestId = String(payload.claimId || payload.id || payload.claimNo || '').trim()
|
||||
const requestId = String(payload.claimId || payload.id || payload.claimNo || payload.documentNo || '').trim()
|
||||
if (!requestId) {
|
||||
return
|
||||
}
|
||||
@@ -423,6 +401,7 @@ function openWorkbenchDocument(payload = {}) {
|
||||
String(item.claimId || '').trim() === requestId
|
||||
|| String(item.id || '').trim() === requestId
|
||||
|| String(item.claimNo || '').trim() === requestId
|
||||
|| String(item.documentNo || '').trim() === requestId
|
||||
))
|
||||
const returnTo = (
|
||||
String(payload.returnTo || '').trim() === 'workbench'
|
||||
@@ -431,7 +410,15 @@ function openWorkbenchDocument(payload = {}) {
|
||||
)
|
||||
? 'workbench'
|
||||
: ''
|
||||
openRequestDetail(request || payload, { returnTo })
|
||||
const detailPayload = request || {
|
||||
...payload,
|
||||
id: payload.id || requestId,
|
||||
claimId: payload.claimId || requestId,
|
||||
claimNo: payload.claimNo || payload.documentNo || requestId,
|
||||
documentNo: payload.documentNo || requestId,
|
||||
detailLookupOnly: true
|
||||
}
|
||||
openRequestDetail(detailPayload, { returnTo })
|
||||
}
|
||||
|
||||
function dispatchAiSidebarCommand(type, payload = null) {
|
||||
@@ -509,12 +496,4 @@ watch(
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
onMounted(() => {
|
||||
playLoginEntryAnimation()
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
stopLoginEntryAnimation()
|
||||
})
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user