import XinTable from '@/components/XinTable'; import { Badge, Button, Image, Space, Typography } from 'antd'; import { LeftOutlined } from '@ant-design/icons'; import type { ICategoryItem } from '@/domain/iCategoryItem'; import type { XinTableColumn } from '@/components/XinTable/typings'; import type { ISysFileInfo } from '@/domain/iSysFile'; import { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useNavigate, useSearchParams } from 'react-router'; import { Create, Update } from '@/api/common/table.ts'; import dayjs from 'dayjs'; const { Title } = 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 CategoryItemPage() { const { t } = useTranslation(); const navigate = useNavigate(); const [searchParams] = useSearchParams(); // 从 URL 参数获取分类信息 const categoryId = searchParams.get('categoryId'); const categoryName = searchParams.get('categoryName') || ''; const [currentCategory, setCurrentCategory] = useState({ id: categoryId ? parseInt(categoryId) : 0, name: decodeURIComponent(categoryName), }); // 监听 URL 参数变化 useEffect(() => { if (categoryId) { setCurrentCategory({ id: parseInt(categoryId), name: decodeURIComponent(categoryName), }); } }, [categoryId, categoryName]); const columns: XinTableColumn[] = [ { title: t('system.category.item.id'), dataIndex: 'id', hideInForm: true, width: 80, align: 'center', }, { title: t('system.category.item.title'), dataIndex: 'title', valueType: 'text', colProps: { span: 12 }, rules: [{ required: true, message: t('system.category.item.title.required') }], }, { title: t('system.category.item.image'), dataIndex: 'image_id', valueType: 'image', colProps: { span: 24 }, rules: [{ required: true, message: t('system.category.item.image.required') }], hideInSearch: true, fieldProps: { action: '/system/file/list/upload', mode: 'single', maxCount: 1, changeType: 'id', }, render: (_value: ISysFileInfo | string, record: ICategoryItem) => { const url = getImageUrl(record.image); if (!url) return '-'; return ( ); }, }, { title: t('system.category.item.link'), dataIndex: 'link', valueType: 'text', colProps: { span: 12 }, hideInSearch: true, fieldProps: { placeholder: t('system.category.item.link.placeholder'), }, }, { title: t('system.category.item.status'), dataIndex: 'status', valueType: 'select', colProps: { span: 12 }, initialValue: 0, rules: [{ required: true, message: t('system.category.item.status.required') }], fieldProps: { options: [ { label: t('system.category.item.status.normal'), value: 0 }, { label: t('system.category.item.status.disabled'), value: 1 }, ], }, render: (value: number) => { return value === 0 ? : ; }, }, { title: t('system.category.item.sort'), dataIndex: 'sort', valueType: 'digit', colProps: { span: 12 }, hideInSearch: true, initialValue: 0, fieldProps: { min: 0, style: { width: '100%' }, }, }, { title: t('system.category.item.createdAt'), dataIndex: 'created_at', render: (value: string) => (value ? dayjs(value).format('YYYY-MM-DD HH:mm') : '-'), hideInForm: true, hideInSearch: true, width: 160, }, ]; // 返回分类列表 const handleGoBack = () => { navigate('/system/category'); }; // 如果没有分类ID,显示提示 if (!currentCategory.id) { return (
{t('system.category.selectCategoryFirst')}
); } return (
<span className={'mr-2'}>{t('system.category.itemManagement')} - {currentCategory.name}</span>
api="/system/category/item" columns={columns} rowKey="id" accessName="system.category.item" formProps={{ grid: true, colProps: { span: 12 }, rowProps: { gutter: [30, 0] }, layout: 'vertical', }} modalProps={{ width: 600 }} requestParams={(params) => { return { ...params, category_id: currentCategory.id, }; }} searchShow={false} handleFinish={async (values, mode, _form, defaultValue) => { if (mode === 'create') { await Create('/system/category/item', { ...values, category_id: currentCategory.id, }); window.$message?.success(t('system.category.item.createSuccess')); } else { await Update('/system/category/item/' + defaultValue?.id, { ...values, category_id: currentCategory.id, }); window.$message?.success(t('system.category.item.updateSuccess')); } return true; }} />
); }