文件
yjyf/server/application/api/controller/Coupon.php
linda 4734724ed2 feat: 后端补齐前端所需模块 + 后台登录页品牌化重构
后端(补齐前端已入口但无接口的模块):
- Coupon 控制器:center 领券中心 / my 我的券(未使用·已使用·已过期+计数)/ receive 领取
  含库存与过期校验、重复领取拦截、领券后自动发消息
- Message 控制器:index 列表(分类筛选)/ read 单条已读 / readAll 全部已读 / unread 角标
  支持 user 与 master 两种归属

前端(对应页面,全部接真接口):
- pages/address/list  服务地址:列表 / 新增·编辑弹层 / 设为默认 / 删除
- pages/coupon/coupon 领券中心 + 我的券(双 Tab + 状态筛选 + 计数)
- pages/message/message 消息中心:分类 / 未读圆点 / 点开自动已读 / 全部已读 / 跳订单
- mine.vue 三个入口(地址·优惠券·消息)由「开发中」改为真实路由
- merchant/workbench 服务地址入口接真实路由
- 首页 TabBar「消息」接入消息中心
- api.js 新增 coupon/message 共 7 个接口

后台登录页(UI 与前端主色调统一):
- 左侧橙金渐变品牌区:logo 徽标 + 「优匠优服」立体字 + slogan + 460万+/99.9%/1762万 平台实力 + 保障条
- 右侧白色登录卡:橙色渐变按钮、圆角输入框、错误提示条
- 保留 FastAdmin 全部挂钩(token/验证码/keeplogin/@AdminLoginFormBegin 等 14 项)

验证:5 套用例 178 项断言全通过(47+65+27+24+15),配置自检 8/8
2026-10-28 16:51:45 +08:00

134 行
5.1 KiB
PHP

<?php
namespace app\api\controller;
use think\Db;
/**
* 优惠券:领券中心 / 我的券 / 领取
*/
class Coupon extends Base
{
/**
* 领券中心(可领取的券)
*/
public function center()
{
$uid = $this->uid();
$now = time();
$list = Db::name('coupon')
->where('status', 'normal')
->where(function ($q) use ($now) {
$q->where('end_time', 0)->whereOr('end_time', '>', $now);
})
->order('amount desc,id desc')
->select();
$receivedIds = Db::name('user_coupon')->where('user_id', $uid)->column('coupon_id');
foreach ($list as &$row) {
$row['amount'] = (float)$row['amount'];
$row['min_amount'] = (float)$row['min_amount'];
$row['discount'] = (float)$row['discount'];
$row['total'] = (int)$row['total'];
$row['received'] = (int)$row['received'];
$row['received_by_me'] = in_array((int)$row['id'], array_map('intval', $receivedIds), true);
$row['sold_out'] = $row['total'] > 0 && $row['received'] >= $row['total'];
$row['time_text'] = (int)$row['end_time'] > 0 ? date('Y.m.d', (int)$row['end_time']) . ' 到期' : '长期有效';
$row['value_text'] = $row['type'] === 'cash'
? ('¥' . (float)$row['amount'])
: (rtrim(rtrim(number_format((float)$row['discount'] * 10, 1, '.', ''), '0'), '.') . ' 折');
$row['rule_text'] = $row['min_amount'] > 0 ? ('满 ¥' . (float)$row['min_amount'] . ' 可用') : '无门槛';
}
unset($row);
$this->success('', ['list' => $list]);
}
/**
* 我的优惠券
* @ApiParams (name="status", type="string", required=false, description="unused|used|expired")
*/
public function my()
{
$status = $this->request->param('status', 'unused');
if (!in_array($status, ['unused', 'used', 'expired'], true)) {
$status = 'unused';
}
$uid = $this->uid();
$now = time();
$list = Db::name('user_coupon')->alias('uc')
->join('coupon c', 'c.id = uc.coupon_id', 'LEFT')
->field('uc.id,uc.status,uc.use_time,uc.createtime,c.name,c.type,c.amount,c.discount,c.min_amount,c.end_time')
->where('uc.user_id', $uid)
->where('uc.status', $status)
->order('uc.id desc')
->select();
$counts = ['unused' => 0, 'used' => 0, 'expired' => 0];
$all = Db::name('user_coupon')->where('user_id', $uid)->field('status,count(*) as c')->group('status')->select();
foreach ($all as $r) {
$counts[$r['status']] = (int)$r['c'];
}
foreach ($list as &$row) {
$row['amount'] = (float)$row['amount'];
$row['min_amount'] = (float)$row['min_amount'];
$row['discount'] = (float)$row['discount'];
$row['value_text'] = $row['type'] === 'cash'
? ('¥' . (float)$row['amount'])
: (rtrim(rtrim(number_format((float)$row['discount'] * 10, 1, '.', ''), '0'), '.') . ' 折');
$row['rule_text'] = $row['min_amount'] > 0 ? ('满 ¥' . (float)$row['min_amount'] . ' 可用') : '无门槛';
$row['time_text'] = (int)$row['end_time'] > 0 ? ('有效期至 ' . date('Y.m.d', (int)$row['end_time'])) : '长期有效';
$row['expired'] = (int)$row['end_time'] > 0 && (int)$row['end_time'] < $now;
}
unset($row);
$this->success('', ['list' => $list, 'counts' => $counts]);
}
/**
* 领取优惠券
* @ApiMethod (POST)
*/
public function receive()
{
$couponId = (int)$this->request->post('coupon_id');
$coupon = Db::name('coupon')->where('id', $couponId)->where('status', 'normal')->find();
if (!$coupon) {
$this->error('优惠券不存在或已下架');
}
if ((int)$coupon['end_time'] > 0 && (int)$coupon['end_time'] < time()) {
$this->error('优惠券已过期');
}
if ((int)$coupon['total'] > 0 && (int)$coupon['received'] >= (int)$coupon['total']) {
$this->error('优惠券已被领完');
}
$has = Db::name('user_coupon')->where('user_id', $this->uid())->where('coupon_id', $couponId)->find();
if ($has) {
$this->error('您已领取过该优惠券');
}
Db::startTrans();
try {
Db::name('user_coupon')->insert([
'user_id' => $this->uid(),
'coupon_id' => $couponId,
'status' => 'unused',
'createtime' => time(),
]);
Db::name('coupon')->where('id', $couponId)->setInc('received');
Db::commit();
} catch (\Exception $e) {
Db::rollback();
$this->error('领取失败:' . $e->getMessage());
}
$this->notify('user', $this->uid(), '优惠券领取成功', '「' . $coupon['name'] . '」已放入我的优惠券', 'system', 0);
$this->success('领取成功');
}
}