后端(补齐前端已入口但无接口的模块): - 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
134 行
5.1 KiB
PHP
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('领取成功');
|
|
}
|
|
}
|