feat: enhance layout components, data layer and global styles

- SidebarRail, TopBar, FilterBar: improved navigation and filtering UX

- metrics.js, requests.js: expanded data with multi-range trend series

- composables: enhanced useChat, useNavigation, useRequests

- global.css: refined design tokens and utility classes

- Add DocFilterBar component and LoginView page

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-04-29 23:35:56 +08:00
parent 7141e1d11a
commit e54ebd072a
15 changed files with 845 additions and 199 deletions

View File

@@ -3,30 +3,52 @@ import { initialRequests } from '../data/requests.js'
export function useRequests() {
const requests = ref(initialRequests)
const entityMap = {
'Northstar China Ltd.': 'Northstar China Ltd.',
'Northstar Singapore Pte.': 'Northstar Singapore Pte.',
'Northstar US Inc.': 'Northstar US Inc.'
}
const search = ref('')
const filters = reactive({ entity: '全部主体', category: '全部费用', risk: '全部风险' })
const ranges = ['今日', '本周', '本月']
const activeRange = ref('今日')
const activeRange = ref('本周')
const filteredRequests = computed(() => {
const key = search.value.trim().toLowerCase()
return requests.value.filter((item) => {
const matchesSearch = !key || `${item.id}${item.person}${item.category}${item.risk}`.toLowerCase().includes(key)
const matchesCategory = filters.category === '全部费用' || item.category.includes(filters.category.replace('交通', ''))
const matchesRisk = filters.risk === '全部风险' || (filters.risk === '高风险' ? item.status === 'danger' : item.verdict.includes(filters.risk.replace('低风险', '通过')))
return matchesSearch && matchesCategory && matchesRisk
const matchesEntity = filters.entity === '全部主体' || item.entity === entityMap[filters.entity]
const matchesCategory = filters.category === '全部费用' || item.category === filters.category
const matchesRisk = filters.risk === '全部风险'
|| (filters.risk === '高风险' && item.status === 'danger')
|| (filters.risk === '需解释' && item.status === 'warning')
|| (filters.risk === '低风险' && item.status === 'success')
const matchesRange = activeRange.value === '本月'
|| (activeRange.value === '本周' && item.range !== '本月')
|| (activeRange.value === '今日' && item.range === '今日')
return matchesSearch && matchesEntity && matchesCategory && matchesRisk && matchesRange
})
})
function updateRequest(requestId, updates) {
requests.value = requests.value.map((item) => (item.id === requestId ? { ...item, ...updates } : item))
}
function approveRequest(request) {
request.verdict = '已通过'
request.status = 'success'
updateRequest(request.id, {
verdict: '已通过',
status: 'success',
risk: '已完成人工确认'
})
return `${request.id} 已标记为通过,审计日志已更新。`
}
function rejectRequest(request) {
request.verdict = '已退回补件'
request.status = 'danger'
updateRequest(request.id, {
verdict: '已退回补件',
status: 'danger',
risk: '待申请人补充差旅行程与票据'
})
return `${request.id} 已退回,系统将通知申请人补充材料。`
}