chore: 将已合并的商务工作台同步回主工作区
This commit is contained in:
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 => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[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)">&'), '<img src=x onerror="alert(1)">&')
|
||||
})
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user