feat: 数字员工财务报告体系与定时提醒及看板快照调度
- 新增数字员工财务报告生成、邮件投递与渲染调度器 - 引入员工画像扫描调度与定时提醒任务 - 完善财务看板快照、排行口径与部门人员占比计算 - 优化数字员工工作看板仪表盘与技能目录 - 增强前端总览页图表、工作台摘要与顶部导航栏交互 - 新增差旅申请规划推动提醒与报销创建会话状态管理 - 补充财务报告、看板调度、数字员工工作记录测试覆盖
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { computed, onMounted, ref, watch } from 'vue'
|
||||
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
||||
|
||||
import {
|
||||
fetchDigitalEmployeeDashboard,
|
||||
@@ -92,6 +92,9 @@ export function useOverviewView(options = {}) {
|
||||
const riskDashboardPayload = ref(null)
|
||||
const riskDashboardLoading = ref(false)
|
||||
const riskDashboardError = ref(null)
|
||||
const riskDashboardLastUpdatedAt = ref('')
|
||||
let riskDashboardRefreshTimer = 0
|
||||
let riskDashboardRequestSeq = 0
|
||||
const digitalEmployeeDashboardPayload = ref(null)
|
||||
const digitalEmployeeDashboardLoading = ref(false)
|
||||
const digitalEmployeeDashboardError = ref(null)
|
||||
@@ -178,22 +181,53 @@ export function useOverviewView(options = {}) {
|
||||
}
|
||||
|
||||
const loadRiskDashboard = async () => {
|
||||
const requestSeq = ++riskDashboardRequestSeq
|
||||
riskDashboardLoading.value = true
|
||||
riskDashboardError.value = null
|
||||
|
||||
try {
|
||||
riskDashboardPayload.value = await fetchRiskObservationDashboard({
|
||||
const payload = await fetchRiskObservationDashboard({
|
||||
windowDays: activeRiskWindowDays.value,
|
||||
limit: 500
|
||||
})
|
||||
if (requestSeq !== riskDashboardRequestSeq) {
|
||||
return
|
||||
}
|
||||
riskDashboardPayload.value = payload
|
||||
riskDashboardLastUpdatedAt.value = new Date().toISOString()
|
||||
} catch (error) {
|
||||
if (requestSeq !== riskDashboardRequestSeq) {
|
||||
return
|
||||
}
|
||||
riskDashboardPayload.value = null
|
||||
riskDashboardError.value = error
|
||||
} finally {
|
||||
riskDashboardLoading.value = false
|
||||
if (requestSeq === riskDashboardRequestSeq) {
|
||||
riskDashboardLoading.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const startRiskDashboardRealtimeRefresh = () => {
|
||||
if (riskDashboardRefreshTimer) {
|
||||
window.clearInterval(riskDashboardRefreshTimer)
|
||||
}
|
||||
riskDashboardRefreshTimer = window.setInterval(() => {
|
||||
if (document.visibilityState === 'hidden' || riskDashboardLoading.value) {
|
||||
return
|
||||
}
|
||||
void loadRiskDashboard()
|
||||
}, 30_000)
|
||||
}
|
||||
|
||||
const stopRiskDashboardRealtimeRefresh = () => {
|
||||
if (!riskDashboardRefreshTimer) {
|
||||
return
|
||||
}
|
||||
window.clearInterval(riskDashboardRefreshTimer)
|
||||
riskDashboardRefreshTimer = 0
|
||||
}
|
||||
|
||||
const loadDigitalEmployeeDashboard = async () => {
|
||||
digitalEmployeeDashboardLoading.value = true
|
||||
digitalEmployeeDashboardError.value = null
|
||||
@@ -222,6 +256,11 @@ export function useOverviewView(options = {}) {
|
||||
void loadSystemDashboard()
|
||||
void loadRiskDashboard()
|
||||
void loadDigitalEmployeeDashboard()
|
||||
startRiskDashboardRealtimeRefresh()
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
stopRiskDashboardRealtimeRefresh()
|
||||
})
|
||||
|
||||
watch(
|
||||
@@ -323,6 +362,9 @@ export function useOverviewView(options = {}) {
|
||||
const financeDepartmentRanking = computed(() => (
|
||||
financeDashboardPayload.value?.departmentRanking || []
|
||||
))
|
||||
const financeDepartmentEmployeeMix = computed(() => (
|
||||
financeDashboardPayload.value?.departmentEmployeeMix || emptyFinanceDonut
|
||||
))
|
||||
const financeEmployeeRanking = computed(() => (
|
||||
financeDashboardPayload.value?.employeeRanking || []
|
||||
))
|
||||
@@ -501,7 +543,11 @@ export function useOverviewView(options = {}) {
|
||||
const activeTrend = computed(() => financeTrend.value)
|
||||
const spendTotal = computed(() => financeSpendByCategory.value.reduce((sum, item) => sum + Number(item.value || 0), 0))
|
||||
const riskTotal = computed(() => financeExceptionMix.value.reduce((sum, item) => sum + Number(item.value || 0), 0))
|
||||
const departmentEmployeeTotal = computed(() => (
|
||||
financeDepartmentEmployeeMix.value.reduce((sum, item) => sum + Number(item.value || item.amount || 0), 0)
|
||||
))
|
||||
const spendCenterValue = computed(() => formatCurrency(Math.round(spendTotal.value)))
|
||||
const departmentEmployeeCenterValue = computed(() => formatCurrency(Math.round(departmentEmployeeTotal.value)))
|
||||
|
||||
const spendLegend = computed(() => financeSpendByCategory.value.map((item) => ({
|
||||
...item,
|
||||
@@ -513,6 +559,14 @@ export function useOverviewView(options = {}) {
|
||||
display: `${item.value} 单`
|
||||
})))
|
||||
|
||||
const departmentEmployeeLegend = computed(() => financeDepartmentEmployeeMix.value.map((item) => ({
|
||||
...item,
|
||||
value: Number(item.value || item.amount || 0),
|
||||
display: departmentEmployeeTotal.value
|
||||
? `${Math.round((Number(item.value || item.amount || 0) / departmentEmployeeTotal.value) * 100)}%`
|
||||
: '0%'
|
||||
})))
|
||||
|
||||
const systemToolTotal = computed(() =>
|
||||
systemToolCallMix.reduce((sum, item) => sum + item.value, 0)
|
||||
)
|
||||
@@ -542,6 +596,7 @@ export function useOverviewView(options = {}) {
|
||||
rank: index + 1,
|
||||
shortName: item.name,
|
||||
amountLabel: formatCurrency(item.amount),
|
||||
meta: `${Number(item.employeeCount || 0)} 人 / ${Number(item.count || 0)} 单`,
|
||||
width: `${Math.max((item.amount / max) * 100, 18)}%`,
|
||||
color: item.color
|
||||
}))
|
||||
@@ -561,6 +616,7 @@ export function useOverviewView(options = {}) {
|
||||
rank: index + 1,
|
||||
shortName: item.name,
|
||||
amountLabel: formatCurrency(item.amount),
|
||||
meta: `${item.department || '未归属部门'} / ${Number(item.count || 0)} 单`,
|
||||
width: `${Math.max((item.amount / max) * 100, 18)}%`,
|
||||
color: item.color
|
||||
}))
|
||||
@@ -738,6 +794,8 @@ export function useOverviewView(options = {}) {
|
||||
bottlenecks,
|
||||
budgetMetrics,
|
||||
budgetSummary,
|
||||
departmentEmployeeCenterValue,
|
||||
departmentEmployeeLegend,
|
||||
departmentRangeOptions,
|
||||
digitalEmployeeCategoryRows,
|
||||
digitalEmployeeDashboard,
|
||||
@@ -760,6 +818,7 @@ export function useOverviewView(options = {}) {
|
||||
rankedEmployees,
|
||||
riskDashboard,
|
||||
riskDashboardError,
|
||||
riskDashboardLastUpdatedAt,
|
||||
riskDashboardLoading,
|
||||
riskDailyTrendRows,
|
||||
riskLegend,
|
||||
|
||||
Reference in New Issue
Block a user