import XinTable from '@/components/XinTable'; import { Badge, Image, Tag, Typography } from 'antd'; import { useEffect, useState } from 'react'; import type { IGridNav } from '@/domain/iGridNav'; import type { ICategory } from '@/domain/iCategory'; import type { XinTableColumn } from '@/components/XinTable/typings'; import type { ISysFileInfo } from '@/domain/iSysFile'; import { List } from '@/api/common/table'; import { useTranslation } from 'react-i18next'; import dayjs from 'dayjs'; const { Title, Text } = Typography; /** * 从 image 字段中提取预览 URL * image 字段可能是 ISysFileInfo 对象或 URL 字符串 */ function getImageUrl(image: ISysFileInfo | string | null | undefined): string { if (!image) return ''; if (typeof image === 'string') return image; return image.preview_url || image.file_url || ''; } /** 首页宫格导航管理 */ export default function GridNavPage() { const { t } = useTranslation(); // 分类下拉选项 const [categoryOptions, setCategoryOptions] = useState<{ label: string; value: number }[]>([]); useEffect(() => { List('/system/category', { pageSize: 1000 }).then((res) => { const list = res.data?.data?.data ?? []; setCategoryOptions(list.map((item) => ({ label: item.name, value: item.id as number, }))); }).catch(() => { // 分类加载失败不影响页面使用 }); }, []); const columns: XinTableColumn[] = [ { title: t('system.gridNav.id'), dataIndex: 'id', hideInForm: true, width: 80, sorter: true, align: 'center', }, { title: t('system.gridNav.title'), dataIndex: 'title', valueType: 'text', colProps: { span: 12 }, rules: [{ required: true, message: t('system.gridNav.title.required') }], }, { title: t('system.gridNav.image'), dataIndex: 'image_id', valueType: 'image', colProps: { span: 24 }, rules: [{ required: true, message: t('system.gridNav.image.required') }], hideInSearch: true, fieldProps: { action: '/system/file/list/upload', mode: 'single', maxCount: 1, changeType: 'id' }, render: (_value: ISysFileInfo | string, record: IGridNav) => { const url = getImageUrl(record.image); if (!url) return '-'; return ( ); }, }, { title: t('system.gridNav.linkType'), dataIndex: 'link_type', valueType: 'select', colProps: { span: 12 }, initialValue: 0, rules: [{ required: true, message: t('system.gridNav.linkType.required') }], fieldProps: { options: [ { label: t('system.gridNav.linkType.link'), value: 0 }, { label: t('system.gridNav.linkType.category'), value: 1 }, ], }, render: (value: number) => { return value === 1 ? {t('system.gridNav.linkType.category')} : {t('system.gridNav.linkType.link')}; }, }, { title: t('system.gridNav.link'), dataIndex: 'link', valueType: 'text', colProps: { span: 12 }, hideInSearch: true, fieldProps: { placeholder: t('system.gridNav.link.placeholder'), }, render: (_, record) => { if(record.link_type === 1) { const name = record.category?.name; return name ? {name} : '-'; } return record.link || '-' }, dependency: { dependencies: ['link_type'], visible: (values) => values.link_type !== 1, }, }, { title: t('system.carousel.category'), dataIndex: 'category_id', valueType: 'select', colProps: { span: 12 }, hideInSearch: true, hideInTable: true, fieldProps: { options: categoryOptions, showSearch: true, optionFilterProp: 'label', placeholder: t('system.carousel.category.placeholder'), }, dependency: { dependencies: ['link_type'], visible: (values) => values.link_type === 1, }, }, { title: t('system.gridNav.status'), dataIndex: 'status', valueType: 'select', filters: [ { text: t('system.gridNav.status.normal'), value: 0 }, { text: t('system.gridNav.status.disabled'), value: 1 }, ], colProps: { span: 12 }, rules: [{ required: true, message: t('system.gridNav.status.required') }], fieldProps: { options: [ { label: t('system.gridNav.status.normal'), value: 0 }, { label: t('system.gridNav.status.disabled'), value: 1 }, ], }, render: (value: number) => { return value === 0 ? : ; }, }, { title: t('system.gridNav.sort'), dataIndex: 'sort', valueType: 'digit', colProps: { span: 12 }, hideInSearch: true, initialValue: 0, fieldProps: { min: 0, style: { width: '100%' }, }, }, { title: t('system.gridNav.createdAt'), dataIndex: 'created_at', render: (value: string) => (value ? dayjs(value).format('YYYY-MM-DD HH:mm') : '-'), hideInForm: true, hideInSearch: true, width: 160, }, ]; return ( <>
{t('system.gridNav.page.title')} {t('system.gridNav.page.description')}
api="/system/grid-nav" columns={columns} rowKey="id" accessName="system.grid-nav" formProps={{ grid: true, colProps: { span: 12 }, rowProps: { gutter: [30, 0] }, layout: 'vertical', }} modalProps={{ width: 800 }} searchProps={false} scroll={{ x: 1000 }} /> ); }