chore: 将已合并的商务工作台同步回主工作区

This commit is contained in:
Yvan
2026-11-05 10:57:06 +08:00
parent ee20692e95
commit 297a892518
10 changed files with 1304 additions and 121 deletions
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,32 @@
import { channelCount, channelMoney } from '../../sw/channel-display.js'
const definitions = [
{ key: 'todayRegister', label: '玩家注册' },
{ key: 'todayActive', label: '活跃玩家' },
{ key: 'todayPay', label: '充值金额', money: true },
{ key: 'effectivePromote', label: '有效端' },
{ key: 'activePromote', label: '活跃渠道数' },
{ key: 'newPromote', label: '新增渠道数' },
{ key: 'lockedPromote', label: '锁定渠道', event: true },
{ key: 'terminatedPromote', label: '解除合作渠道', event: true }
]
export const overviewCards = (data) => definitions.map(definition => {
const metric = data?.cards?.[definition.key]
const known = data?.available !== false && metric?.value != null
const changeRate = metric?.changeRate == null ? null : Number(metric.changeRate)
const label = metric?.compareLabel || '较上一同期'
const change = !known ? metric?.compareLabel || '—' : changeRate == null ? `${label}:无可比数据` : `${changeRate > 0 ? '+' : ''}${changeRate.toFixed(1)}% ${label}`
return {
...definition,
value: known ? (definition.money ? channelMoney(metric.value) : channelCount(String(metric.value).split('.')[0])) : !data ? '—' : data.available === false || definition.event ? '未接入' : '未获取',
change,
up: known && changeRate > 0,
down: known && changeRate < 0,
tip: definition.key === 'effectivePromote'
? `渠道注册后 ${data?.settings?.days ?? 30} 天内充值满 ¥${data?.settings?.amount ?? 3000},按达标日期统计。`
: definition.event ? '按所选区间内的状态变更事件统计。' : '所选时间区间内的数据,与上一等长周期比较。'
}
})
export const escapeChartText = value => String(value ?? '').replace(/[&<>"']/g, c => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c]))
@@ -0,0 +1,24 @@
import test from 'node:test'
import assert from 'node:assert/strict'
import { overviewCards, escapeChartText } from './dashboard-metrics.js'
test('overview preserves exact money, eight cards, and unavailable event data', () => {
const cards = overviewCards({ available: true, settings: { days: 15, amount: 500 }, cards: {
todayPay: { value: '9007199254740993.01', changeRate: null },
todayRegister: { value: '0.00', changeRate: '0' },
todayActive: { value: '5998.00', changeRate: '2.1' },
lockedPromote: { value: null, compareLabel: '事件数据未接入' }
} })
assert.equal(cards.length, 8)
assert.equal(cards.find(c => c.key === 'todayPay').value, '¥9,007,199,254,740,993.01')
assert.equal(cards.find(c => c.key === 'todayRegister').value, '0')
assert.equal(cards.find(c => c.key === 'todayActive').value, '5,998')
assert.equal(cards.find(c => c.key === 'lockedPromote').value, '未接入')
assert.match(cards.find(c => c.key === 'effectivePromote').tip, /15 天内充值满 ¥500/)
assert.ok(overviewCards(null).every(c => c.value === '—'))
assert.ok(overviewCards({ available: false }).every(c => c.value === '未接入'))
})
test('chart HTML tooltips escape provider-controlled names', () => {
assert.equal(escapeChartText('<img src=x onerror="alert(1)">&'), '&lt;img src=x onerror=&quot;alert(1)&quot;&gt;&amp;')
})
+1 -12
View File
@@ -1,23 +1,12 @@
<template>
<div class="h-full kra-container2 overflow-auto bg-main">
<div class="space-y-2 py-2">
<business-dashboard>
<template #heading>
<div>
<h1 class="text-xl font-semibold text-base-text">欢迎回来,{{ userStore.userInfo.nickName }}</h1>
<p class="mt-2 text-sm text-muted-foreground">{{ today }} · 商务工作台</p>
</div>
</template>
</business-dashboard>
<business-dashboard />
</div>
</div>
</template>
<script setup>
import { computed } from 'vue'
import { useUserStore } from '@/pinia/modules/user'
import BusinessDashboard from './components/BusinessDashboard.vue'
defineOptions({ name: 'Dashboard' })
const userStore = useUserStore()
const today = computed(() => new Date().toLocaleDateString('zh-CN'))
</script>