feat: 新增发票抬头、晒单、钱包日志等模型及后台管理功能
- 新增 invoice_title、showcase、wallet_log 模型及对应语言包 - 新增后台控制器、视图及搜索字段配置 - 修复服务类目删除保护逻辑 - 优化后台登录页面文案及样式 - 新增前端角色切换逻辑及页面拦截 - 新增 SVG 图标及样式变量 - 修复接口权限及下拉框默认值问题
这个提交包含在:
@@ -3,20 +3,22 @@
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use think\Db;
|
||||
use think\exception\PDOException;
|
||||
|
||||
/**
|
||||
* 消息中心
|
||||
* 消息通知中心
|
||||
*
|
||||
* @icon fa fa-circle-o
|
||||
* @icon fa fa-bell-o
|
||||
*/
|
||||
class Message extends Backend
|
||||
{
|
||||
|
||||
/**
|
||||
* Message模型对象
|
||||
* @var \app\admin\model\Message
|
||||
*/
|
||||
protected $model = null;
|
||||
protected $searchFields = 'id,title,content';
|
||||
|
||||
public function _initialize()
|
||||
{
|
||||
@@ -26,13 +28,189 @@ class Message extends Backend
|
||||
$this->view->assign("typeList", $this->model->getTypeList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 消息列表(批量补齐接收人真实姓名/昵称、手机号及关联工单号)
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$this->request->filter(['strip_tags', 'trim']);
|
||||
if (false === $this->request->isAjax()) {
|
||||
return $this->view->fetch();
|
||||
}
|
||||
if ($this->request->request('keyField')) {
|
||||
return $this->selectpage();
|
||||
}
|
||||
[$where, $sort, $order, $offset, $limit] = $this->buildparams();
|
||||
$list = $this->model
|
||||
->where($where)
|
||||
->order($sort, $order)
|
||||
->paginate($limit);
|
||||
|
||||
$rows = $list->items();
|
||||
$userIds = [];
|
||||
$masterIds = [];
|
||||
$orderIds = [];
|
||||
foreach ($rows as $r) {
|
||||
if ($r['receive_type'] === 'master' && (int)$r['receive_id'] > 0) {
|
||||
$masterIds[] = (int)$r['receive_id'];
|
||||
} elseif ($r['receive_type'] === 'user' && (int)$r['receive_id'] > 0) {
|
||||
$userIds[] = (int)$r['receive_id'];
|
||||
}
|
||||
if ((int)$r['order_id'] > 0) {
|
||||
$orderIds[] = (int)$r['order_id'];
|
||||
}
|
||||
}
|
||||
|
||||
$userMap = $userIds
|
||||
? Db::name('user')->where('id', 'in', array_unique($userIds))->column('id,nickname,username,mobile', 'id')
|
||||
: [];
|
||||
$masterMap = $masterIds
|
||||
? Db::name('master')->where('id', 'in', array_unique($masterIds))->column('id,realname,mobile', 'id')
|
||||
: [];
|
||||
$orderMap = $orderIds
|
||||
? Db::name('order')->where('id', 'in', array_unique($orderIds))->column('order_no', 'id')
|
||||
: [];
|
||||
|
||||
foreach ($rows as &$item) {
|
||||
$rid = (int)$item['receive_id'];
|
||||
if ($item['receive_type'] === 'master') {
|
||||
$m = $masterMap[$rid] ?? null;
|
||||
$item['receiver_name'] = $m ? ($m['realname'] ?: ('师傅#' . $rid)) : ('师傅#' . $rid);
|
||||
$item['receiver_mobile'] = $m['mobile'] ?? '';
|
||||
} else {
|
||||
$u = $userMap[$rid] ?? null;
|
||||
$item['receiver_name'] = $u ? ($u['nickname'] ?: ($u['username'] ?: ('用户#' . $rid))) : ('用户#' . $rid);
|
||||
$item['receiver_mobile'] = $u['mobile'] ?? '';
|
||||
}
|
||||
$oid = (int)$item['order_id'];
|
||||
$item['order_no'] = $oid > 0 ? ($orderMap[$oid] ?? '') : '';
|
||||
}
|
||||
unset($item);
|
||||
|
||||
return json(['total' => $list->total(), 'rows' => $rows]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
|
||||
* 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
|
||||
* 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
|
||||
* 消息详情回看
|
||||
*/
|
||||
public function detail($ids = null)
|
||||
{
|
||||
$row = $this->model->get($ids);
|
||||
if (!$row) {
|
||||
$this->error(__('No Results were found'));
|
||||
}
|
||||
$receiver = [];
|
||||
if ($row['receive_type'] === 'master' && (int)$row['receive_id'] > 0) {
|
||||
$m = Db::name('master')->where('id', (int)$row['receive_id'])->field('id,realname,mobile,city')->find();
|
||||
if ($m) {
|
||||
$receiver = ['name' => $m['realname'], 'mobile' => $m['mobile'], 'extra' => $m['city'] ?: '认证师傅'];
|
||||
}
|
||||
} elseif ((int)$row['receive_id'] > 0) {
|
||||
$u = Db::name('user')->where('id', (int)$row['receive_id'])->field('id,nickname,username,mobile')->find();
|
||||
if ($u) {
|
||||
$receiver = ['name' => $u['nickname'] ?: $u['username'], 'mobile' => $u['mobile'], 'extra' => '平台注册用户'];
|
||||
}
|
||||
}
|
||||
$order = (int)$row['order_id'] > 0
|
||||
? Db::name('order')->where('id', (int)$row['order_id'])->field('id,order_no,service_name,pay_amount,status')->find()
|
||||
: null;
|
||||
|
||||
$this->view->assign([
|
||||
'row' => $row,
|
||||
'receiver' => $receiver,
|
||||
'order' => $order ?: [],
|
||||
]);
|
||||
return $this->view->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* 下发站内通知(支持选择单个或多个用户/师傅批量推送)
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
if (false === $this->request->isPost()) {
|
||||
return $this->view->fetch();
|
||||
}
|
||||
$params = $this->request->post('row/a', []);
|
||||
$receiveType = in_array($params['receive_type'] ?? '', ['user', 'master'], true) ? $params['receive_type'] : 'user';
|
||||
$rawIds = $receiveType === 'master'
|
||||
? ($params['receive_master_id'] ?? ($params['receive_id'] ?? ''))
|
||||
: ($params['receive_user_id'] ?? ($params['receive_id'] ?? ''));
|
||||
|
||||
$idArr = array_values(array_unique(array_filter(array_map('intval', explode(',', (string)$rawIds)))));
|
||||
if (!$idArr) {
|
||||
$this->error('请至少选择一位消息接收对象');
|
||||
}
|
||||
$title = trim((string)($params['title'] ?? ''));
|
||||
$content = trim((string)($params['content'] ?? ''));
|
||||
if ($title === '' || $content === '') {
|
||||
$this->error('通知标题与正文内容不能为空');
|
||||
}
|
||||
$msgType = in_array($params['type'] ?? '', ['order', 'system', 'audit', 'remind'], true) ? $params['type'] : 'system';
|
||||
$orderId = max(0, (int)($params['order_id'] ?? 0));
|
||||
$isRead = !empty($params['is_read']) ? 1 : 0;
|
||||
$now = time();
|
||||
|
||||
$insertRows = [];
|
||||
foreach ($idArr as $rid) {
|
||||
$insertRows[] = [
|
||||
'receive_type' => $receiveType,
|
||||
'receive_id' => $rid,
|
||||
'type' => $msgType,
|
||||
'title' => mb_substr($title, 0, 100),
|
||||
'content' => mb_substr($content, 0, 500),
|
||||
'order_id' => $orderId,
|
||||
'is_read' => $isRead,
|
||||
'createtime' => $now,
|
||||
];
|
||||
}
|
||||
|
||||
Db::startTrans();
|
||||
try {
|
||||
Db::name('message')->insertAll($insertRows);
|
||||
Db::commit();
|
||||
} catch (PDOException|\Exception $e) {
|
||||
Db::rollback();
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
$this->success('成功发送 ' . count($insertRows) . ' 条站内通知');
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑站内通知
|
||||
*/
|
||||
public function edit($ids = null)
|
||||
{
|
||||
$row = $this->model->get($ids);
|
||||
if (!$row) {
|
||||
$this->error(__('No Results were found'));
|
||||
}
|
||||
if (false === $this->request->isPost()) {
|
||||
$this->view->assign('row', $row);
|
||||
return $this->view->fetch();
|
||||
}
|
||||
$params = $this->request->post('row/a', []);
|
||||
$receiveType = in_array($params['receive_type'] ?? '', ['user', 'master'], true) ? $params['receive_type'] : $row['receive_type'];
|
||||
$receiveId = $receiveType === 'master'
|
||||
? (int)($params['receive_master_id'] ?? ($params['receive_id'] ?? 0))
|
||||
: (int)($params['receive_user_id'] ?? ($params['receive_id'] ?? 0));
|
||||
if ($receiveId <= 0) {
|
||||
$this->error('请选择有效的接收对象');
|
||||
}
|
||||
|
||||
$data = [
|
||||
'receive_type' => $receiveType,
|
||||
'receive_id' => $receiveId,
|
||||
'type' => in_array($params['type'] ?? '', ['order', 'system', 'audit', 'remind'], true) ? $params['type'] : $row['type'],
|
||||
'order_id' => max(0, (int)($params['order_id'] ?? 0)),
|
||||
'title' => mb_substr(trim((string)($params['title'] ?? '')), 0, 100),
|
||||
'content' => mb_substr(trim((string)($params['content'] ?? '')), 0, 500),
|
||||
'is_read' => !empty($params['is_read']) ? 1 : 0,
|
||||
];
|
||||
if ($data['title'] === '' || $data['content'] === '') {
|
||||
$this->error('通知标题与正文内容不能为空');
|
||||
}
|
||||
$row->save($data);
|
||||
$this->success();
|
||||
}
|
||||
}
|
||||
|
||||
在新工单中引用
屏蔽一个用户