在后端管理页面首页增加"图标发布"菜单,用于管理首页轮播图和分类图标的上传。使用现有的文件上传组件,上传后保存文件ID并关联文件实体。
// 首页图标实体 - 支持轮播图和分类图标
@Entity('home_icons')
export class HomeIcon {
@PrimaryGeneratedColumn({ unsigned: true })
id!: number;
@Column({ name: 'title', type: 'varchar', length: 255, comment: '图标标题' })
title!: string;
@Column({ name: 'type', type: 'varchar', length: 20, comment: '图标类型: banner, category' })
type!: string;
@Column({ name: 'file_id', type: 'int', unsigned: true, comment: '关联文件ID' })
fileId!: number;
@ManyToOne(() => File)
@JoinColumn({ name: 'file_id', referencedColumnName: 'id' })
file!: File;
@Column({ name: 'sort_order', type: 'int', default: 0, comment: '排序顺序' })
sortOrder!: number;
@Column({ name: 'is_enabled', type: 'tinyint', default: 1, comment: '是否启用: 0-禁用, 1-启用' })
isEnabled!: number;
@Column({ name: 'link_url', type: 'varchar', length: 512, nullable: true, comment: '链接地址' })
linkUrl!: string | null;
@Column({ name: 'description', type: 'text', nullable: true, comment: '描述信息' })
description!: string | null;
@CreateDateColumn({ name: 'created_at' })
createdAt!: Date;
@UpdateDateColumn({ name: 'updated_at' })
updatedAt!: Date;
}
import { GenericCrudService } from '@/server/utils/generic-crud.service';
import { HomeIcon } from './home-icon.entity';
export class HomeIconService extends GenericCrudService<HomeIcon> {
constructor(dataSource: DataSource) {
super(dataSource, HomeIcon);
}
async getBanners(): Promise<HomeIcon[]> {
return this.getList(1, 100, undefined, undefined, {
type: 'banner',
isEnabled: 1
});
}
async getCategoryIcons(): Promise<HomeIcon[]> {
return this.getList(1, 100, undefined, undefined, {
type: 'category',
isEnabled: 1
});
}
}
使用通用CRUD路由创建标准RESTful API:
const HomeIconsPage: React.FC = () => {
const [activeTab, setActiveTab] = useState<'banner' | 'category'>('banner');
return (
<PageContainer>
<Tabs activeKey={activeTab} onChange={setActiveTab}>
<TabPane tab="轮播图管理" key="banner">
<BannerTable />
</TabPane>
<TabPane tab="分类图标管理" key="category">
<CategoryIconTable />
</TabPane>
</Tabs>
</PageContainer>
);
};
{
key: 'home-icons',
label: '图标发布',
icon: <PictureOutlined />,
path: '/admin/home-icons'
}
{
path: 'home-icons',
element: <HomeIconsPage />,
errorElement: <ErrorPage />
}
const UploadSection: React.FC<{ type: 'banner' | 'category' }> = ({ type }) => {
const handleUploadSuccess = (fileKey: string, fileUrl: string, file: File) => {
// 创建新的图标记录
createHomeIcon({
title: file.name,
type,
fileId: extractFileIdFromKey(fileKey),
sortOrder: 0,
isEnabled: 1
});
};
return (
<MinioUploader
uploadPath={`/home-icons/${type}`}
accept="image/*"
maxSize={5}
onUploadSuccess={handleUploadSuccess}
buttonText={`上传${type === 'banner' ? '轮播图' : '分类图标'}`}
/>
);
};
CREATE TABLE `home_icons` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL DEFAULT '' COMMENT '图标标题',
`type` varchar(20) NOT NULL DEFAULT '' COMMENT '图标类型: banner, category',
`file_id` int(11) unsigned NOT NULL COMMENT '关联文件ID',
`sort_order` int(11) NOT NULL DEFAULT '0' COMMENT '排序顺序',
`is_enabled` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否启用: 0-禁用, 1-启用',
`link_url` varchar(512) DEFAULT NULL COMMENT '链接地址',
`description` text COMMENT '描述信息',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_type_enabled` (`type`, `is_enabled`),
KEY `idx_sort_order` (`sort_order`),
KEY `idx_file_id` (`file_id`),
CONSTRAINT `fk_home_icon_file` FOREIGN KEY (`file_id`) REFERENCES `file` (`id`) ON DELETE RESTRICT ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='首页图标管理表';
HomeIconHomeIconServiceHomeIconsPageGET /api/v1/home-icons?type=banner&isEnabled=1
GET /api/v1/home-icons?type=category&isEnabled=1
### 创建图标
POST /api/v1/home-icons { "title": "首页轮播图1", "type": "banner", "fileId": 123, "sortOrder": 1, "isEnabled": 1, "linkUrl": "https://example.com", "description": "首页主banner" } ```