import type { ColumnDef } from '@tanstack/vue-table' import type { Composer } from 'vue-i18n' import { Ban, CheckCircle, Mail, MoreHorizontal, Settings, Shield, Trash2, } from 'lucide-vue-next' import { h } from 'vue' import type { App } from '../data/schema' import { Copy } from '@/components/sva-ui/copy' import Button from '@/components/ui/button/Button.vue' import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu' export function getColumns(actions: { onGoToSettings: (app: App) => void onGoToSecurity: (app: App) => void onGoToEmail: (app: App) => void onToggleStatus: (app: App) => void onDelete: (app: App) => void }, t: Composer['t']): ColumnDef[] { const billingTypeMap: Record = { free: { label: '免费', class: 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300' }, subscription: { label: '订阅', class: 'bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-300' }, time: { label: '计时', class: 'bg-purple-100 text-purple-800 dark:bg-purple-900 dark:text-purple-300' }, count: { label: '计次', class: 'bg-orange-100 text-orange-800 dark:bg-orange-900 dark:text-orange-300' }, } const loginPolicyMap: Record = { loose: { label: '宽松', class: 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300' }, strict: { label: '严格', class: 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-300' }, hybrid: { label: '混合', class: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-300' }, } const statusMap: Record = { active: { label: '启用', class: 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300' }, inactive: { label: '禁用', class: 'bg-gray-100 text-gray-800 dark:bg-gray-800 dark:text-gray-300' }, } return [ { accessorKey: 'name', header: () => '应用名称', cell: ({ row }) => h('div', { class: 'flex items-center space-x-3' }, [ h('div', { class: 'h-8 w-8 rounded bg-primary/10 flex items-center justify-center flex-shrink-0 overflow-hidden' }, [ row.original.icon_url ? h('img', { src: `http://localhost:8080${row.original.icon_url}`, alt: row.getValue('name') as string, class: 'w-full h-full object-cover', }) : h('span', { class: 'text-primary font-bold text-sm' }, (row.getValue('name') as string).charAt(0).toUpperCase()), ]), h('div', { class: 'flex flex-col' }, [ h('p', { class: 'font-medium' }, row.getValue('name') as string), h('p', { class: 'text-xs text-muted-foreground truncate max-w-[200px]' }, row.original.description), ]), ]), }, { accessorKey: 'app_key', header: () => 'App Key', cell: ({ row }) => { const appKey = row.getValue('app_key') as string return h('div', { class: 'flex items-center space-x-2' }, [ h('code', { class: 'text-xs bg-muted px-2 py-1 rounded font-mono' }, appKey || '-'), appKey && h(Copy, { class: 'h-4 w-4', size: 'sm', content: appKey }), ]) }, }, { accessorKey: 'billing_type', header: () => '运营模式', cell: ({ row }) => { const billingType = row.getValue('billing_type') as string const info = billingTypeMap[billingType] if (!info) return h('span', {}, billingType) return h('span', { class: `px-2 py-1 rounded text-xs ${info.class}` }, info.label) }, }, { accessorKey: 'login_policy', header: () => '登录策略', cell: ({ row }) => { const loginPolicy = row.getValue('login_policy') as string const info = loginPolicyMap[loginPolicy] if (!info) return h('span', {}, loginPolicy) return h('span', { class: `px-2 py-1 rounded text-xs ${info.class}` }, info.label) }, }, { accessorKey: 'enable_trial', header: () => '试用', cell: ({ row }) => { const enableTrial = row.getValue('enable_trial') as boolean return h('span', { class: `px-2 py-1 rounded text-xs ${enableTrial ? 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300' : 'bg-gray-100 text-gray-800 dark:bg-gray-800 dark:text-gray-300'}`, }, enableTrial ? `${row.original.trial_balance}余额` : '无') }, }, { accessorKey: 'status', header: () => '状态', cell: ({ row }) => { const status = row.getValue('status') as string const info = statusMap[status] if (!info) return h('span', {}, status) return h('span', { class: `px-2 py-1 rounded text-xs ${info.class}` }, info.label) }, }, { accessorKey: 'created_at', header: () => '创建时间', cell: ({ row }) => { const createdAt = row.getValue('created_at') if (!createdAt) return '-' try { const date = new Date(createdAt as string) if (Number.isNaN(date.getTime())) return '-' return date.toLocaleDateString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', }) } catch { return '-' } }, }, { id: 'actions', header: () => h('span', { class: 'sr-only' }, t('common.actions')), cell: ({ row }) => { const app = row.original const isActive = app.status === 'active' return h( DropdownMenu, {}, { default: () => [ h(DropdownMenuTrigger, { asChild: true }, () => h(Button, { variant: 'ghost', class: 'h-8 w-8 p-0' }, () => [ h(MoreHorizontal, { class: 'h-4 w-4' }), h('span', { class: 'sr-only' }, t('common.openMenu')), ])), h( DropdownMenuContent, { align: 'end' }, () => [ h(DropdownMenuItem, { onClick: () => actions.onGoToSettings(app) }, () => [ h(Settings, { class: 'mr-2 h-4 w-4' }), '基本设置', ]), h(DropdownMenuItem, { onClick: () => actions.onGoToSecurity(app) }, () => [ h(Shield, { class: 'mr-2 h-4 w-4' }), '安全设置', ]), h(DropdownMenuItem, { onClick: () => actions.onGoToEmail(app) }, () => [ h(Mail, { class: 'mr-2 h-4 w-4' }), '邮箱设置', ]), h(DropdownMenuSeparator), h(DropdownMenuItem, { onClick: () => actions.onToggleStatus(app) }, () => [ isActive ? h(Ban, { class: 'mr-2 h-4 w-4' }) : h(CheckCircle, { class: 'mr-2 h-4 w-4' }), isActive ? '禁用' : '启用', ]), h(DropdownMenuSeparator), h(DropdownMenuItem, { class: 'text-destructive', onClick: () => actions.onDelete(app) }, () => [ h(Trash2, { class: 'mr-2 h-4 w-4' }), t('developer.applications.delete'), ]), ], ), ], }, ) }, }, ] }