feat(sync): 后端功能模块与前端模块数据同源 + 后台13个业务模块可管

前端不再写死运营数据:
- 首页 Banner/保障条/教程卡 改由 /api/home/index 下发(fa_banner + fa_config),
  数据缺失或停用自动回落内置兜底文案
- 订单状态提示改由后端 OrderStatus::tip() 下发 status_tip,前后端一套口径

后台可管(FastAdmin 生成器):
- 新增 13 个业务后台模块:运营位/订单/师傅/商家/优惠券/评价/消息/服务/服务类目/申诉/开票/提现/结算单
  (controller + model + view + fa_auth_rule 菜单 78 条)

修复:
- nginx /admin/* 改为 301 到 /admin.php/*,否则后台菜单点开全部 404

验证:tests/phase5_data_sync.js 新增 16 项联动断言;全量回归 202 项断言 0 失败
这个提交包含在:
linda
2026-10-28 17:06:55 +08:00
父节点 4734724ed2
当前提交 4e0c86ca06
共有 72 个文件被更改,包括 4977 次插入 和 23 次删除

查看文件

@@ -30,12 +30,12 @@ class Home extends Base
->select();
$data = [
'cats' => $cats,
'hot' => $this->formatServices($hot),
'banners' => [
['id' => 1, 'title' => '家装季 · 双11狂欢大促', 'desc' => '下单立减 · 满额再返券', 'date' => '10.23 - 11.15'],
],
'badge' => ['coupon' => 0, 'unread' => 0],
'cats' => $cats,
'hot' => $this->formatServices($hot),
'banners' => $this->banners(),
'assures' => $this->configList('home_assure', '平台认证,先行赔付,极速上门,售后无忧'),
'tutorial' => $this->tutorial(),
'badge' => ['coupon' => 0, 'unread' => 0],
];
if ($this->auth->isLogin()) {
@@ -164,6 +164,62 @@ class Home extends Base
];
}
/**
* 首页运营位(后台 fa_banner 可管,缺省回落到内置文案)
*/
protected function banners()
{
$rows = Db::name('banner')->where('status', 'normal')->order('weigh desc,id desc')->limit(5)->select();
if (!$rows) {
return [[
'id' => 0, 'badge' => '家装季', 'title' => '双11 狂欢大促',
'subtitle' => '下单立减 · 满额再返券', 'date_text' => '10.23 - 11.15',
'image' => '', 'link' => '',
]];
}
$ret = [];
foreach ($rows as $r) {
$ret[] = [
'id' => (int)$r['id'],
'badge' => $r['badge'],
'title' => $r['title'],
'subtitle' => $r['subtitle'],
'date_text' => $r['date_text'],
'image' => $r['image'],
'link' => $r['link'],
];
}
return $ret;
}
/**
* 读取 fa_config 中的逗号分隔列表
*/
protected function configList($name, $default = '')
{
$v = Db::name('config')->where('name', $name)->value('value');
if (!$v) {
$v = $default;
}
return array_values(array_filter(array_map('trim', explode(',', (string)$v))));
}
/**
* 首页教程卡(fa_config: 标题|副标题)
*/
protected function tutorial()
{
$v = Db::name('config')->where('name', 'home_tutorial')->value('value');
if (!$v) {
return ['title' => '下单找师傅教程', 'sub' => '3 分钟看懂,下单不踩坑'];
}
$parts = explode('|', (string)$v);
return [
'title' => trim($parts[0]),
'sub' => isset($parts[1]) ? trim($parts[1]) : '',
];
}
/**
* 列表格式化
*/