914e3d5127
- 添加云端数据权限列到代理管理页面 - 重构代理后台用户管理、卡密管理、财务管理页面使用DataTable组件 - 添加统计卡片到代理后台各页面 - 修复agent-apps相关类型错误 - 添加代理后台页面i18n国际化支持 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
87 lines
3.4 KiB
TypeScript
87 lines
3.4 KiB
TypeScript
import type { ColumnDef } from '@tanstack/vue-table'
|
|
import type { Composer } from 'vue-i18n'
|
|
|
|
import { ArrowDownLeft, ArrowUpRight, RotateCcw } from 'lucide-vue-next'
|
|
import { h } from 'vue'
|
|
|
|
import type { Transaction } from '../data/schema'
|
|
|
|
import Badge from '@/components/ui/badge/Badge.vue'
|
|
|
|
export function getColumns(t: Composer['t']): ColumnDef<Transaction>[] {
|
|
return [
|
|
{
|
|
accessorKey: 'type',
|
|
header: () => t('agent.finance.columns.type'),
|
|
cell: ({ row }) => {
|
|
const type = row.getValue('type') as string
|
|
const typeMap: Record<string, { label: string, variant: 'default' | 'secondary' | 'destructive', icon: any }> = {
|
|
recharge: { label: t('agent.finance.types.recharge'), variant: 'default', icon: ArrowDownLeft },
|
|
consume: { label: t('agent.finance.types.consume'), variant: 'secondary', icon: ArrowUpRight },
|
|
refund: { label: t('agent.finance.types.refund'), variant: 'default', icon: RotateCcw },
|
|
}
|
|
const config = typeMap[type] || { label: type, variant: 'secondary', icon: ArrowUpRight }
|
|
const iconClass = type === 'recharge' ? 'text-green-500' : type === 'refund' ? 'text-blue-500' : 'text-red-500'
|
|
const bgClass = type === 'recharge' ? 'bg-green-500/10' : type === 'refund' ? 'bg-blue-500/10' : 'bg-red-500/10'
|
|
|
|
return h('div', { class: 'flex items-center gap-2' }, [
|
|
h('div', { class: `size-8 rounded-lg flex items-center justify-center ${bgClass}` }, [
|
|
h(config.icon, { class: `size-4 ${iconClass}` }),
|
|
]),
|
|
h('span', config.label),
|
|
])
|
|
},
|
|
},
|
|
{
|
|
accessorKey: 'description',
|
|
header: () => t('agent.finance.columns.description'),
|
|
cell: ({ row }) => {
|
|
const description = row.getValue('description') as string
|
|
const type = row.getValue('type') as string
|
|
return h('span', { class: 'text-muted-foreground' }, description || t(`agent.finance.types.${type}`) || '-')
|
|
},
|
|
},
|
|
{
|
|
accessorKey: 'amount',
|
|
header: () => t('agent.finance.columns.amount'),
|
|
cell: ({ row }) => {
|
|
const type = row.getValue('type') as string
|
|
const amount = row.getValue('amount') as number
|
|
const prefix = type === 'recharge' || type === 'refund' ? '+' : '-'
|
|
const textClass = type === 'recharge' || type === 'refund' ? 'text-green-500' : 'text-red-500'
|
|
return h('span', { class: `font-semibold ${textClass}` }, `${prefix}¥${(amount || 0).toFixed(2)}`)
|
|
},
|
|
},
|
|
{
|
|
accessorKey: 'balance',
|
|
header: () => t('agent.finance.columns.balance'),
|
|
cell: ({ row }) => {
|
|
const balance = row.getValue('balance') as number
|
|
return h('span', { class: 'text-muted-foreground' }, `¥${(balance || 0).toFixed(2)}`)
|
|
},
|
|
},
|
|
{
|
|
accessorKey: 'created_at',
|
|
header: () => t('agent.finance.columns.createdAt'),
|
|
cell: ({ row }) => {
|
|
const createdAt = row.getValue('created_at') as string
|
|
if (!createdAt) return '-'
|
|
try {
|
|
const date = new Date(createdAt)
|
|
if (Number.isNaN(date.getTime())) return '-'
|
|
return h('span', { class: 'text-muted-foreground whitespace-nowrap' }, date.toLocaleString('zh-CN', {
|
|
year: 'numeric',
|
|
month: '2-digit',
|
|
day: '2-digit',
|
|
hour: '2-digit',
|
|
minute: '2-digit',
|
|
}))
|
|
}
|
|
catch {
|
|
return '-'
|
|
}
|
|
},
|
|
},
|
|
]
|
|
}
|