# 6.8 公告与链接管理 :::tip 概述 本节涵盖通知公告(Notice)和友情链接(Link)两个模块,均继承 `BaseTenantService` 实现租户隔离,`use HasFileProcessing` 启用封面/Logo 文件字段处理。 > **说明:** 本文件名为 `content.md`,实际文档内容为通知公告和友情链接两个独立模块,并不存在 "Content" 模块。 ::: ## 通知公告 ### 模块特点 | 特性 | 说明 | |------|------| | 基类 | `BaseTenantService`(租户隔离) | | Trait 组合 | `HasCrudOperations, HasFileProcessing, HasQueryScopes, HasSerializeMaps` | | 文件字段 | `cover`(封面图),保存到 notice 目录 | | 富文本字段 | `content`(正文,存 `[IMG_URL]` 占位,读取时替换回域名) | | 枚举映射 | `type` → notice_type、`status` → notice_status | | 排序 | 按 id 倒序(最新在前)+ 租户内排序 | ### Service 配置(来自项目实际代码) ```php class NoticeService extends BaseTenantService { use HasCrudOperations, HasFileProcessing, HasQueryScopes, HasSerializeMaps; protected string $modelClass = Notice::class; protected array $fileFields = ['cover']; // 富文本字段:保存时迁移媒体并替换为 [IMG_URL] 占位,读取时替换回域名 protected array $contentFields = ['content']; protected string $fileSaveDir = 'notice'; protected array $pageLikeFields = ['title']; protected array $pageEqFields = ['type', 'status']; // 最新公告排在前面 protected array $pageOrderBy = ['field' => 'id', 'type' => 'desc']; protected array $serializeMaps = [ 'type' => 'notice_type', 'status' => 'notice_status', ]; } ``` ### API 接口 | 方法 | 路径 | 权限码 | 说明 | |------|------|--------|------| | GET | `/api/notice/page` | sys:notice:page | 分页列表 | | GET | `/api/notice/list` | — | 全量列表 | | GET | `/api/notice/detail/{id}` | sys:notice:detail | 详情 | | POST | `/api/notice/add` | sys:notice:add | 新增 | | PUT | `/api/notice/update` | sys:notice:update | 修改 | | DELETE | `/api/notice/delete/{id}` | sys:notice:delete | 删除 | | DELETE | `/api/notice/batchDelete` | sys:notice:batchDelete | 批量删除 | --- ## 友情链接 ### 模块特点 | 特性 | 说明 | |------|------| | 基类 | `BaseTenantService`(租户隔离) | | Trait 组合 | `HasCrudOperations, HasFileProcessing, HasQueryScopes, HasSerializeMaps, HasUniqueCheck` | | 文件字段 | `image`(友链 Logo),保存到 link 目录 | | 唯一校验 | `name` 按租户分组唯一(`['name','tenant_id']`) | | 枚举映射 | `status` → link_status 字典 | ### Service 配置(来自项目实际代码) ```php class LinkService extends BaseTenantService { use HasCrudOperations, HasFileProcessing, HasQueryScopes, HasSerializeMaps, HasUniqueCheck; protected string $modelClass = Link::class; protected array $fileFields = ['image']; protected string $fileSaveDir = 'link'; protected array $pageLikeFields = ['name']; protected array $pageEqFields = ['status']; protected array $pageOrderBy = ['field' => 'sort', 'type' => 'asc']; // name 在同一租户内唯一 protected array $uniqueFields = [['name', 'tenant_id']]; protected array $serializeMaps = [ 'status' => 'link_status', ]; } ``` ### API 接口 | 方法 | 路径 | 权限码 | 说明 | |------|------|--------|------| | GET | `/api/link/page` | sys:link:page | 分页列表 | | GET | `/api/link/list` | — | 全量列表 | | GET | `/api/link/detail/{id}` | sys:link:detail | 详情 | | POST | `/api/link/add` | sys:link:add | 新增 | | PUT | `/api/link/update` | sys:link:update | 修改 | | DELETE | `/api/link/delete/{id}` | sys:link:delete | 删除 | | DELETE | `/api/link/batchDelete` | sys:link:batchDelete | 批量删除 | ## 两模块对比 | 维度 | 通知公告 Notice | 友情链接 Link | |------|----------------|--------------| | 核心字段 | title、content(正文)、cover | name、url、image(Logo) | | 默认排序 | id 倒序(最新在前) | sort 升序 | | 唯一校验 | 无 | name 分租户唯一 | | 字典 | notice_type、notice_status | link_status | | 典型场景 | 站内公告、系统通知 | 合作伙伴链接页 |