公告模块
约 2043 字大约 7 分钟
2026-02-03
概述
本文档规定了 ShopXO 系统中公告模块的功能说明、技术架构、数据结构和开发规范,供开发人员参考。
功能说明
公告模块用于向用户展示系统通知、活动公告、促销信息等内容。支持多业务类型、多平台、多页面的精细化展示控制。
核心特性
- 多业务类型: 支持商城、用户、后台三种业务场景
- 平台过滤: 支持 PC、H5、APP 三个平台独立配置
- 页面过滤: 支持指定公告在特定页面显示
- 定时展示: 支持设置公告的开始和结束时间
- 灵活排序: 支持自定义排序权重
- 文本内容: 内容支持多行文本展示
技术架构
后台管理:admin/notice
├── Controller: app/admin/controller/Notice.php
├── Form: app/admin/form/Notice.php
└── View: app/admin/view/default/notice/
前台 API:api/notice
├── Controller: app/api/controller/Notice.php
└── Service: app/service/NoticeService.php
数据存储:
└── sxo_notice (公告表)数据表结构
sxo_notice (公告表)
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
id | int(11) | - | 主键ID |
title | varchar(200) | - | 公告标题 |
content | text | - | 公告内容(多行文本) |
url | varchar(255) | - | 跳转链接 |
business_type | varchar(50) | 'shop' | 业务类型(shop/user/admin) |
platform | json | NULL | 适用平台(["pc","h5","app"]) |
display_pages | json | NULL | 展示页面(["home","list","detail"]) |
is_enable | tinyint(1) | 0 | 是否启用(0=禁用, 1=启用) |
start_time | int(11) | 0 | 开始时间(时间戳) |
end_time | int(11) | 0 | 结束时间(时间戳,0=永久) |
sort | int(11) | 0 | 排序权重(数字越小越靠前) |
add_time | int(11) | - | 添加时间 |
upd_time | int(11) | - | 更新时间 |
字段说明
business_type (业务类型)
| 值 | 说明 | 语言键 |
|---|---|---|
shop | 商城公告 | notice_business_type_shop |
user | 用户公告 | notice_business_type_user |
admin | 后台公告 | notice_business_type_admin |
platform (适用平台)
JSON 数组格式,可多选:
| 值 | 说明 | 语言键 |
|---|---|---|
pc | PC网站 | common_service.notice.platform_pc |
h5 | H5手机网站 | common_service.notice.platform_h5 |
app | APP应用 | common_service.notice.platform_app |
示例:
["pc", "h5"]空数组或 NULL 表示适用于所有平台。
display_pages (展示页面)
JSON 数组格式,可多选:
| 值 | 说明 | 语言键 |
|---|---|---|
home | 首页 | common_service.notice.page_home |
list | 商品列表 | common_service.notice.page_list |
detail | 商品详情 | common_service.notice.page_detail |
checkout | 结算页面 | common_service.notice.page_checkout |
user | 用户中心 | common_service.notice.page_user |
cart | 购物车 | common_service.notice.page_cart |
示例:
["home", "user"]空数组或 NULL 表示适用于所有页面。
Service 层方法
NoticeList
获取公告列表。
参数:
[
'where' => [], // 查询条件
'field' => '', // 查询字段
'order_by' => '', // 排序方式
'm' => 0, // 偏移量
'n' => 10, // 数量
]返回:
[
'code' => 0,
'msg' => '操作成功',
'data' => [...], // 处理后的公告列表
]NoticeInfo
获取公告详情。
参数:
[
'where' => ['id' => 1], // 查询条件
]返回:
[
'code' => 0,
'msg' => '操作成功',
'data' => [
'id' => 1,
'title' => '公告标题',
'content' => '公告内容',
'platform' => ['pc', 'h5'],
'display_pages' => ['home'],
// ...
],
]NoticeSave
保存公告(新增或更新)。
参数:
[
'id' => 1, // 更新时必填
'title' => '公告标题', // 必填
'content' => '公告内容', // 必填
'url' => 'https://example.com', // 必填
'business_type' => 'shop', // 必填
'platform' => ['pc', 'h5'], // 数组
'display_pages' => ['home'], // 数组
'is_enable' => 1,
'start_time' => '2026-01-01 00:00',
'end_time' => '2026-12-31 23:59',
'sort' => 100,
]返回:
[
'code' => 0,
'msg' => '操作成功',
'data' => ['url' => 'admin/Notice/Index'],
]NoticeDelete
删除公告。
参数:
[
'ids' => [1, 2, 3], // 支持数组或逗号分隔字符串
]返回:
[
'code' => 0,
'msg' => '删除成功',
'data' => ['url' => 'admin/Notice/Index'],
]NoticeStatusUpdate
更新公告状态。
参数:
[
'id' => 1,
'field' => 'is_enable',
'value' => 1,
]返回:
[
'code' => 0,
'msg' => '更新成功',
]NoticeApiList
获取 API 公告列表(带平台和页面过滤)。
参数:
[
'platform' => 'h5', // 平台(pc/h5/app)
'page' => 'home', // 页面(home/list/detail等)
'business_type' => 'shop', // 业务类型
]返回:
[
'code' => 0,
'msg' => 'success',
'data' => [
[
'id' => 1,
'title' => '公告标题',
'content' => ['第一行', '第二行'], // 按换行符分割
'url' => '',
'sort' => 100,
// ...
],
],
]前台 API 调用
获取公告列表
请求:
GET /api.php?s=notice/index参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
platform | string | 否 | 平台类型(pc/h5/app),默认 h5 |
page | string | 否 | 页面类型,默认 home |
business_type | string | 否 | 业务类型,默认 shop |
响应示例:
{
"msg": "操作成功",
"code": 0,
"data": [
{
"id": 1,
"title": "xxx",
"content": [
"xxx",
"xxx",
"xxx"
],
"url": "",
"business_type": "shop",
"platform": ["pc", "h5"],
"display_pages": ["home"],
"is_enable": 1,
"sort": 100,
"start_time": "2026-01-20 00:00",
"end_time": 0,
"time_range": "2026-01-20 00:00 ~ 永久"
}
]
}后台管理操作
列表页面
路由: /admin/notice/index
功能:
- 分页展示公告列表
- 搜索筛选(标题、内容、业务类型、平台、页面、状态、时间范围、排序)
- 批量删除
- 状态切换(启用/禁用)
添加/编辑页面
路由: /admin/notice/saveinfo
表单字段:
- 标题(必填)
- 内容(必填,多行文本)
- 跳转链接(必填)
- 业务类型(必填,单选)
- 适用平台(多选)
- 展示页面(多选)
- 是否启用(开关)
- 开始时间(日期时间)
- 结束时间(日期时间,留空为永久)
- 排序(数字)
语言配置
后台语言
文件: app/admin/lang/zh.php(在新窗口打开)
'notice' => [
// 表格列
'form_table' => [
'id' => 'ID',
'title' => '标题',
'content' => '内容',
'business_type' => '业务类型',
'platform' => '适用平台',
'display_pages' => '展示页面',
'is_enable' => '状态',
'time_range' => '有效时间',
'sort' => '排序',
'add_time' => '添加时间',
],
],公共语言
// 业务类型
'notice_business_type_shop' => '商城',
'notice_business_type_user' => '用户',
'notice_business_type_admin' => '后台',
// 展示页面
'notice_display_page_home' => '首页',
'notice_display_page_list' => '商品列表',
'notice_display_page_detail' => '商品详情',
'notice_display_page_checkout' => '结算页面',
'notice_display_page_user' => '用户中心',
'notice_display_page_cart' => '购物车',内容处理规范
platform 和 display_pages 字段
这两个字段存储为 JSON 字符串,但代码中会自动处理为数组。
保存时的处理:
在 NoticeService.php(在新窗口打开) 中:
// 处理数组字段,过滤空值
private static function ProcessArrayField($params, $field, $default = [])
{
if (!isset($params[$field])) {
return $default;
}
$value = $params[$field];
// 确保是数组并过滤空值
if (is_array($value)) {
return array_filter($value, function($item) {
return $item !== '' && $item !== null;
});
}
// 处理字符串格式(ShopXO框架将checkbox处理成逗号分隔的字符串)
if (is_string($value) && trim($value) !== '') {
$arr = explode(',', $value);
return array_filter($arr, function($item) {
return trim($item) !== '';
});
}
return $default;
}读取时的处理:
在 NoticeService.php(在新窗口打开) 中的 NoticeListHandle 方法会自动将 JSON 字符串解析为数组,并生成显示文本。
content 字段处理
- 存储格式: 原始多行文本,保留换行符
- API 返回: 按换行符
\n分割成数组 - 显示: API 端按行展示
示例:
存储: "第一行内容\n第二行内容\n第三行内容"
API返回: ["第一行内容", "第二行内容", "第三行内容"]过滤逻辑
API 获取公告时会应用以下过滤:
时间范围过滤
// 检查是否在有效时间范围内
$current_time = time();
if ($notice['start_time'] > 0 && $notice['start_time'] > $current_time) {
// 未到开始时间,跳过
}
if ($notice['end_time'] > 0 && $notice['end_time'] < $current_time) {
// 已过结束时间,跳过
}平台过滤
// 如果公告指定了平台且不包含当前平台,跳过
$notice_platform = $notice['platform'];
if (!empty($notice_platform) && !in_array($current_platform, $notice_platform)) {
continue;
}页面过滤
// 如果公告指定了页面且不包含当前页面,跳过
$display_pages = $notice['display_pages'];
if (!empty($display_pages) && !in_array($current_page, $display_pages)) {
continue;
}状态过滤
// 只返回启用的公告
$where[] = ['is_enable', '=', 1];使用示例
后台添加公告
use app\service\NoticeService;
$result = NoticeService::NoticeSave([
'title' => '双11大促开启',
'content' => "全场满300减30\n满500减60\n上不封顶",
'url' => '/activity/double11',
'business_type' => 'shop',
'platform' => ['pc', 'h5'],
'display_pages' => ['home', 'list'],
'is_enable' => 1,
'start_time' => '2026-11-01 00:00',
'end_time' => '2026-11-11 23:59',
'sort' => 100,
]);前台获取公告
use app\service\NoticeService;
// H5 首页的商城公告
$result = NoticeService::NoticeApiList([
'platform' => 'h5',
'page' => 'home',
'business_type' => 'shop',
]);
if ($result['code'] == 0) {
$notices = $result['data'];
foreach ($notices as $notice) {
echo $notice['title'] . "\n";
foreach ($notice['content'] as $line) {
echo $line . "\n";
}
}
}开发注意事项
1. JSON 字段处理
platform和display_pages在数据库中存储为 JSON 字符串- Service 层会自动处理 JSON 和数组之间的转换
- 前端表单提交时可以是数组或逗号分隔字符串
2. 时间处理
start_time和end_time存储为时间戳- 0 值表示无限制
- API 返回时会格式化为可读时间范围
3. 内容换行
content字段保留原始换行符- API 返回时会按
\n分割成数组 - 前端遍历数组逐行展示
4. 排序规则
- 按
sort字段升序(数字越小越靠前) - 相同
sort值时按id降序
5. 空数组语义
platform为空数组 → 适用于所有平台display_pages为空数组 → 适用于所有页面
相关文件清单
| 文件路径 | 类型 | 说明 |
|---|---|---|
app/service/NoticeService.php(在新窗口打开) | Service | 公告服务层 |
app/admin/controller/Notice.php(在新窗口打开) | Controller | 后台控制器 |
app/api/controller/Notice.php(在新窗口打开) | Controller | API 控制器 |
app/admin/form/Notice.php(在新窗口打开) | Form | 表格配置 |
app/admin/view/default/notice/(在新窗口打开) | View | 后台视图 |
app/lang/zh.php(在新窗口打开) | Lang | 语言配置 |
app/admin/lang/zh.php(在新窗口打开) | Lang | 后台语言配置 |
