- 框架初始化
 - 安装插件
 - 修复PHP8.4报错
This commit is contained in:
2025-04-19 17:21:20 +08:00
commit c6a4e1f5f6
5306 changed files with 967782 additions and 0 deletions

View File

@@ -0,0 +1,227 @@
<?php
namespace app\admin\controller\shopro\notification;
use app\admin\controller\shopro\Common;
use app\admin\model\shopro\notification\Config as ConfigModel;
use app\admin\controller\shopro\notification\traits\Notification as NotificationTraits;
use addons\shopro\facade\Wechat;
class Config extends Common
{
use NotificationTraits;
public function _initialize()
{
parent::_initialize();
$this->model = new ConfigModel;
}
/**
* 消息通知配置
*/
public function index()
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$receiver_type = $this->request->param('receiver_type');
$notifications = $this->getNotificationsByReceiverType($receiver_type);
$groupConfigs = $this->getGroupConfigs();
foreach ($notifications as $key => &$notification) {
$currentConfigs = $groupConfigs[$notification['event']] ?? [];
foreach ($notification['channels'] as $channel) {
$notification['configs'][$channel] = [
'status' => isset($currentConfigs[$channel]) ? $currentConfigs[$channel]['status'] : 'disabled',
'send_num' => isset($currentConfigs[$channel]) ? $currentConfigs[$channel]['send_num'] : 0,
];
}
}
$this->success('获取成功', null, $notifications);
}
public function detail()
{
$event = $this->request->param('event');
$channel = $this->request->param('channel');
if (!$event || !$channel) {
error_stop('参数错误');
}
$notification = $this->getNotificationByEvent($event);
$notification = $this->formatNotification($notification, $event, $channel);
$this->success('获取成功', null, $notification);
}
// 编辑配置
public function edit($id = null)
{
if (!$this->request->isAjax()) {
return $this->view->fetch();
}
$event = $this->request->param('event');
$channel = $this->request->param('channel');
if ($channel == 'Email') {
$content = $this->request->param('content', '');
} else {
$content = $this->request->param('content/a', []);
}
$type = $this->request->param('type', 'default');
if (!$event || !$channel) {
error_stop('参数错误');
}
$config = $this->model->where('event', $event)->where('channel', $channel)->find();
if (!$config) {
$config = $this->model;
$config->event = $event;
$config->channel = $channel;
}
if (in_array($channel, ['WechatOfficialAccount', 'WechatMiniProgram']) && $type == 'default') {
// 自动组装微信默认模板
$content['fields'] = $this->formatWechatTemplateFields($event, $channel, $content['fields']);
}
$config->type = $type;
$config->content = $content;
$config->save();
$this->success('设置成功');
}
// 配置状态
public function setStatus($event, $channel)
{
$event = $this->request->param('event');
$channel = $this->request->param('channel');
$status = $this->request->param('status', 'disabled');
if (!$event || !$channel) {
$this->error('参数错误');
}
$config = $this->model->where('event', $event)->where('channel', $channel)->find();
if (!$config) {
$config = $this->model;
$config->event = $event;
$config->channel = $channel;
$config->type = 'default';
}
$config->status = $status;
$config->save();
$this->success('设置成功');
}
/**
* 自动获取微信模板 id
*/
public function getTemplateId()
{
$event = $this->request->param('event');
$channel = $this->request->param('channel');
$is_delete = $this->request->param('is_delete', 0);
$template_id = $this->request->param('template_id', '');
if (!$event || !$channel) {
error_stop('参数错误');
}
$notification = $this->getNotificationByEvent($event);
$template = $notification['template'][$channel] ?? null;
if (!$template) {
$this->error('模板不存在');
}
// 请求微信接口
switch ($channel) {
case 'WechatMiniProgram': // 小程序订阅消息
$requestParams['tid'] = $template['tid'];
$requestParams['kid'] = $template['kid'];
$requestParams['sceneDesc'] = $template['scene_desc'];
if (!$requestParams['tid'] || !$requestParams['kid']) {
$this->error('缺少模板参数');
}
$wechat = Wechat::miniProgram()->subscribe_message;
$delete_method = 'deleteTemplate';
$result_key = 'priTmplId';
break;
// case 'WechatOfficialAccount': // 公众号模板消息
// $requestParams['template_id'] = $template['temp_no'];
// if (!$requestParams['template_id']) {
// $this->error('缺少模板参数,获取失败');
// }
// $wechat = Wechat::officialAccount()->template_message; // 微信管理
// $result_key = 'template_id';
// $delete_method = 'deletePrivateTemplate';
// break;
case 'WechatOfficialAccount': // 新版公众号模板消息
$requestParams['template_id'] = $template['temp_no'];
$requestParams['keywords'] = $template['keywords'];
if (!$requestParams['template_id']) {
$this->error('公众号类目模板库目前不完善,请自行在公众号后台->模板消息->选择模板配置');
}
if (!$requestParams['keywords']) {
$this->error('缺少模板关键字,获取失败');
}
$wechat = new \addons\shopro\library\easywechatPlus\WechatOfficialTemplate(Wechat::officialAccount());
$result_key = 'template_id';
$delete_method = 'deletePrivateTemplate';
break;
case 'WechatOfficialAccountBizsend': // 公众号订阅消息(待补充)
$requestParams['tid'] = $template['tid'];
$requestParams['kid'] = $template['kid'];
if (!$requestParams['tid'] || !$requestParams['kid']) {
$this->error('缺少模板参数,获取失败');
}
$wechat = Wechat::officialAccount()->subscribe_message; // 微信管理
$result_key = 'priTmplId';
$delete_method = 'deleteTemplate';
break;
default:
$this->error('当前发送渠道不能获取模板');
break;
}
$result = $wechat->addTemplate(...array_values($requestParams));
if ($result['errcode'] != 0) {
$this->error('获取失败: errcode:' . $result['errcode'] . '; errmsg:' . $result['errmsg']);
} else {
if ($is_delete) {
// 删除传入的老模板
if ($template_id) {
$deleteResult = $wechat->{$delete_method}($template_id);
}
// 删除数据库的老模板
$config = $this->model->where('event', $event)->where('channel', $channel)->find();
$template_id = $config ? ($config->content['template_id'] ?? null) : null;
if ($template_id) {
$deleteResult = $wechat->{$delete_method}($template_id);
}
}
}
$this->success('获取成功', null, ($result[$result_key] ?? null));
}
}

View File

@@ -0,0 +1,128 @@
<?php
namespace app\admin\controller\shopro\notification;
use app\admin\controller\shopro\Common;
use app\admin\model\shopro\notification\Notification as NotificationModel;
use app\admin\model\shopro\Admin;
class Notification extends Common
{
protected $noNeedRight = ['index', 'read', 'delete', 'notificationType'];
public function _initialize()
{
parent::_initialize();
$this->model = new NotificationModel;
}
/**
* 获取管理员的消息列表
*
* @return \think\Response
*/
public function index()
{
$admin = auth_admin();
$admin = Admin::where('id', $admin['id'])->find();
$notifiable_type = $admin->getNotifiableType();
$notifications = NotificationModel::sheepFilter(false)
->where('notifiable_type', $notifiable_type)
->where('notifiable_id', $admin['id'])
->order('createtime', 'desc')
->paginate($this->request->param('list_rows', 10));
$this->success('消息列表', null, $notifications);
}
/**
* 指定消息标记已读
*
* @param string $id
* @return void
*/
public function read($id)
{
$admin = auth_admin();
$admin = Admin::where('id', $admin['id'])->find();
$notifiable_type = $admin->getNotifiableType();
$notification = NotificationModel::sheepFilter()
->where('notifiable_type', $notifiable_type)
->where('notifiable_id', $admin['id'])
->where('id', $id)
->find();
if (!$notification) {
$this->error(__('No Results were found'));
}
$notification->read_time = time();
$notification->save();
$this->success('已读成功', null, $notification);
}
/**
* 删除已读消息
*
* @return void
*/
public function delete()
{
$admin = auth_admin();
$admin = Admin::where('id', $admin['id'])->find();
// 将已读的消息全部删除
$notifiable_type = $admin->getNotifiableType();
NotificationModel::sheepFilter()
->where('notifiable_type', $notifiable_type)
->where('notifiable_id', $admin['id'])
->whereNotNull('read_time')
->delete();
$this->success('删除成功');
}
/**
* 消息类别,以及未读消息数
*
* @return void
*/
public function notificationType()
{
$admin = auth_admin();
$notificationType = NotificationModel::$notificationType;
$newType = [];
foreach ($notificationType as $type => $name) {
// 未读消息数
$unread_num = NotificationModel::where('notifiable_type', 'admin')->where('notifiable_id', $admin['id'])
->notificationType($type)
->where('read_time', null)
->order('createtime', 'desc')->count();
$newType[] = [
'label' => $name,
'value' => $type,
'unread_num' => $unread_num
];
}
$result = [
'unread_num' => array_sum(array_column($newType, 'unread_num')),
'notification_type' => $newType
];
$this->success('消息类型', null, $result);
}
}

View File

@@ -0,0 +1,183 @@
<?php
namespace app\admin\controller\shopro\notification\traits;
/**
* 消息通知,额外方法
*/
trait Notification
{
protected $notificationTypes = [
\addons\shopro\notification\order\OrderNew::class,
\addons\shopro\notification\order\OrderDispatched::class,
\addons\shopro\notification\order\aftersale\OrderAftersaleChange::class,
\addons\shopro\notification\order\aftersale\OrderAdminAftersaleChange::class,
\addons\shopro\notification\order\OrderRefund::class,
\addons\shopro\notification\order\OrderApplyRefund::class,
// 商品
\addons\shopro\notification\goods\StockWarning::class,
// 钱包
\addons\shopro\notification\wallet\CommissionChange::class,
\addons\shopro\notification\wallet\MoneyChange::class,
\addons\shopro\notification\wallet\ScoreChange::class,
// 活动
\addons\shopro\notification\activity\GrouponFail::class,
\addons\shopro\notification\activity\GrouponFinish::class,
];
/**
* 根据接收人类型,获取消息类型
*
* @param array|string $receiverType
* @return array
*/
protected function getNotificationsByReceiverType($receiverType = 'user')
{
$receiverType = is_array($receiverType) ? $receiverType : [$receiverType];
$notifications = $this->getNotifications();
$receiverNotifications = [];
foreach ($notifications as $notification) {
if (in_array($notification['receiver_type'], $receiverType)) {
$receiverNotifications[] = $notification;
}
}
return $receiverNotifications;
}
/**
* 根据事件类型获取消息
*
* @param string $event
* @return void
*/
protected function getNotificationByEvent($event)
{
$notifications = $this->getNotifications();
$notifications = array_column($notifications, null, 'event');
return $notifications[$event] ?? null;
}
/**
* 按照事件类型获取配置分组
*
* @param string $event
* @return array
*/
protected function getGroupConfigs($event = null)
{
// 获取所有配置
$configs = $this->model->select();
$newConfigs = [];
foreach ($configs as $config) {
$newConfigs[$config['event']][$config['channel']] = $config;
}
return $event ? ($newConfigs[$event] ?? []) : $newConfigs;
}
/**
* 获取所有消息类型
*
* @return array
*/
protected function getNotifications()
{
$types = [];
foreach ($this->notificationTypes as $key => $class_name) {
$class = new $class_name();
$currentFields = $class->returnField;
$currentFields['event'] = $class->event;
$currentFields['receiver_type'] = $class->receiver_type;
$currentFields['template'] = $class->template;
$types[] = $currentFields;
}
return $types;
}
/**
* 格式化详情返回结果
*
* @param array $notification
* @param string $event
* @param string $channel
* @return array
*/
protected function formatNotification($notification, $event, $channel)
{
$currentConfigs = $this->getGroupConfigs($event);
$currentConfig = $currentConfigs[$channel] ?? null;
if (in_array($channel, ['WechatOfficialAccount', 'WechatMiniProgram', 'WechatOfficialAccountBizsend'])) {
$currentTemplate = $notification['template'][$channel] ?? [];
unset($notification['template']);
$notification['wechat'] = $currentTemplate;
}
$notification['type'] = $currentConfig['type'] ?? 'default';
$content = $currentConfig['content'] ?? null;
if (!is_array($content)) {
$notification['content_text'] = $content;
}
if ($content && is_array($content)) {
$contentFields = [];
if (isset($content['fields']) && $content['fields']) { // 判断数组是否存在 fields 设置
$contentFields = array_column($content['fields'], null, 'field');
}
$tempFields = array_column($notification['fields'], null, 'field');
$configField = array_merge($tempFields, $contentFields);
$content['fields'] = array_values($configField);
$notification['content'] = $content;
} else {
$notification['content'] = [
'template_id' => '',
'fields' => $notification['fields']
];
}
unset($notification['fields']);
return $notification;
}
/**
* 格式化微信公众号,小程序默认模板时 自动配置 模板字段
*
* @return void
*/
protected function formatWechatTemplateFields($event, $channel, $fields)
{
$notification = $this->getNotificationByEvent($event);
$channelFields = $notification['template'][$channel]['fields'] ?? [];
$channelFields = array_column($channelFields, null, 'field');
foreach ($fields as $key => &$field) {
$field_name = $field['field'] ?? '';
if ($field_name && isset($channelFields[$field_name])) {
$field['template_field'] = $channelFields[$field_name]['template_field'] ?? '';
}
}
return $fields;
}
}