| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535 |
- <?php
- namespace app\admin\controller;
- use app\common\controller\Backend;
- use app\common\library\Sms as SmsLib;
- use app\common\model\AppointmentEmailLog as AppointmentEmailLogModel;
- use app\common\model\AppointmentRecord as AppointmentRecordModel;
- use app\common\model\AppointmentSmsLog as AppointmentSmsLogModel;
- use think\facade\Db;
- use think\facade\Event;
- use think\facade\Validate;
- class Appointment extends Backend
- {
- protected $modelClass = null;
- protected $modelValidate = false;
- protected function initialize()
- {
- parent::initialize();
- $this->modelClass = new AppointmentRecordModel();
- $this->assign('statusList', $this->modelClass->getStatusList());
- $this->assign('submitSmsStatusList', $this->modelClass->getSubmitSmsStatusList());
- $this->assign('batchSmsStatusList', $this->modelClass->getBatchSmsStatusList());
- $this->assign('notifyChannelList', $this->modelClass->getNotifyChannelList());
- $activityList = Db::name('cms_yuyue')->field('id,title')->order('id desc')->select()->toArray();
- $this->assign('activityList', $activityList);
- }
- protected function getTranslatedActivity(int $activityId, string $lang): array
- {
- $lang = strtolower(trim($lang));
- if ($lang === '') {
- $lang = 'cn';
- }
- $query = Db::name('cms_yuyue_data')->where('did', $activityId);
- $row = (clone $query)->where('lang', $lang)->find();
- if (!$row && $lang !== 'cn') {
- $row = (clone $query)->where('lang', 'cn')->find();
- }
- return is_array($row) ? $row : [];
- }
- protected function loadActivityConfig(int $activityId, string $lang): array
- {
- $activity = Db::name('cms_yuyue')->where('id', $activityId)->find();
- if (!is_array($activity) || empty($activity)) {
- return [];
- }
- $translatedActivity = $this->getTranslatedActivity($activityId, $lang);
- if (is_array($translatedActivity) && !empty($translatedActivity)) {
- $activity = array_merge($activity, $translatedActivity);
- }
- return $activity;
- }
- protected function sendAppointmentEmail(string $email, string $subject, string $content): array
- {
- try {
- $config = get_addon_config('phpmailer');
- if (!$config) {
- return [false, 'NO_CONFIG', '未找到 phpmailer 插件配置'];
- }
- $mailer = new \addons\phpmailer\library\Mailer($config);
- $result = $mailer->to($email)->subject($subject)->message($content, true)->send();
- if ($result) {
- return [true, 'SUCCESS', '邮件发送成功'];
- }
- return [false, 'FAIL', $mailer->getError() ?: '邮件发送失败'];
- } catch (\Throwable $e) {
- return [false, 'EXCEPTION', $e->getMessage()];
- }
- }
- public function index()
- {
- if ($this->request->isAjax()) {
- $page = (int)$this->request->param('page/d', 1);
- $limit = (int)$this->request->param('limit/d', 20);
- $sort = (string)$this->request->param('sort/s', 'id');
- $order = (string)$this->request->param('order/s', 'desc');
- $activityId = (int)$this->request->param('activity_id/d', 0);
- $mobile = trim((string)$this->request->param('mobile/s', ''));
- $email = trim((string)$this->request->param('email/s', ''));
- $lang = trim((string)$this->request->param('lang/s', ''));
- $notifyChannel = trim((string)$this->request->param('notify_channel/s', ''));
- $status = $this->request->param('status/s', '');
- $appointmentAutoSms = $this->request->param('appointment_auto_sms/s', '');
- $submitSmsStatus = $this->request->param('submit_sms_status/s', '');
- $batchSmsStatus = $this->request->param('batch_sms_status/s', '');
- $query = $this->modelClass;
- if ($activityId > 0) {
- $query = $query->where('activity_id', $activityId);
- }
- if ($appointmentAutoSms !== '') {
- $activityIds = Db::name('cms_yuyue')->where('appointment_auto_sms', (int)$appointmentAutoSms)->column('id');
- $activityIds = $activityIds ?: [0];
- $query = $query->where('activity_id', 'in', $activityIds);
- }
- if ($mobile !== '') {
- $query = $query->where('mobile', 'like', '%' . $mobile . '%');
- }
- if ($email !== '') {
- $query = $query->where('email', 'like', '%' . $email . '%');
- }
- if ($lang !== '') {
- $query = $query->where('lang', $lang);
- }
- if ($notifyChannel !== '') {
- $query = $query->where('notify_channel', $notifyChannel);
- }
- if ($status !== '') {
- $query = $query->where('status', (int)$status);
- }
- if ($submitSmsStatus !== '') {
- $query = $query->where('submit_sms_status', (int)$submitSmsStatus);
- }
- if ($batchSmsStatus !== '') {
- $query = $query->where('batch_sms_status', (int)$batchSmsStatus);
- }
- $count = $query->count();
- $data = $query->order($sort, $order)->page($page, $limit)->select();
- $activityMap = Db::name('cms_yuyue')->column('appointment_auto_sms', 'id');
- foreach ($data as $item) {
- $item->appointment_auto_sms = isset($activityMap[$item->activity_id]) ? (int)$activityMap[$item->activity_id] : 0;
- }
- return json(['code' => 0, 'count' => $count, 'data' => $data]);
- }
- return $this->fetch();
- }
- public function sendSms()
- {
- if (!$this->request->isPost()) {
- $this->error('请求方式错误');
- }
- $ids = $this->request->post('ids/a', []);
- if (!$ids) {
- $this->error('请先选择预约记录');
- }
- if (!Event::hasListener('sms_notice')) {
- $this->error('未检测到短信通知插件监听 sms_notice');
- }
- $rows = $this->modelClass->where('id', 'in', $ids)->where('notify_channel', 'sms')->select();
- if ($rows->isEmpty()) {
- $this->error('未找到可发送的短信预约记录');
- }
- $success = 0;
- $failed = 0;
- $skipped = 0;
- foreach ($rows as $row) {
- if ((int)$row->batch_sms_status === 1) {
- $skipped++;
- continue;
- }
- $now = time();
- $activityConfig = $this->loadActivityConfig((int)$row->activity_id, (string)$row->lang);
- if (empty($activityConfig)) {
- AppointmentSmsLogModel::create([
- 'record_id' => $row->id,
- 'activity_id' => $row->activity_id,
- 'mobile' => $row->mobile,
- 'sms_type' => 'appointment_batch',
- 'template_code' => '',
- 'content' => '',
- 'status' => 2,
- 'response_code' => 'NO_ACTIVITY',
- 'response_msg' => '活动配置不存在,无法发送统一短信',
- 'retry_count' => 0,
- 'send_time' => 0,
- 'createtime' => $now,
- 'updatetime' => $now,
- ]);
- $row->batch_sms_status = 2;
- $row->updatetime = $now;
- $row->save();
- $failed++;
- continue;
- }
- $activityTitle = trim((string)($activityConfig['title'] ?? $row->activity_title ?? ''));
- $batchTpl = trim((string)($activityConfig['batch_sms_content'] ?? ''));
- $content = $batchTpl !== ''
- ? str_replace('{title}', $activityTitle, $batchTpl)
- : '您预约的【' . $activityTitle . '】已有最新动态,欢迎及时关注官方发布信息。';
- $sendResult = SmsLib::notice($row->mobile, $content, null);
- AppointmentSmsLogModel::create([
- 'record_id' => $row->id,
- 'activity_id' => $row->activity_id,
- 'mobile' => $row->mobile,
- 'sms_type' => 'appointment_batch',
- 'template_code' => '',
- 'content' => $content,
- 'status' => $sendResult ? 1 : 2,
- 'response_code' => $sendResult ? 'SUCCESS' : 'FAIL',
- 'response_msg' => $sendResult ? '后台批量短信发送成功' : '后台批量短信发送失败',
- 'retry_count' => 0,
- 'send_time' => $sendResult ? $now : 0,
- 'createtime' => $now,
- 'updatetime' => $now,
- ]);
- $row->activity_title = $activityTitle;
- $row->batch_sms_status = $sendResult ? 1 : 2;
- $row->batch_sms_time = $sendResult ? $now : $row->batch_sms_time;
- $row->updatetime = $now;
- $row->save();
- $sendResult ? $success++ : $failed++;
- }
- $this->success('统一发送短信完成:成功 ' . $success . ' 条,失败 ' . $failed . ' 条,跳过 ' . $skipped . ' 条');
- }
- public function sendEmail()
- {
- if (!$this->request->isPost()) {
- $this->error('请求方式错误');
- }
- $ids = $this->request->post('ids/a', []);
- if (!$ids) {
- $this->error('请先选择预约记录');
- }
- $rows = $this->modelClass->where('id', 'in', $ids)->where('notify_channel', 'email')->select();
- if ($rows->isEmpty()) {
- $this->error('未找到可发送的邮件预约记录');
- }
- $success = 0;
- $failed = 0;
- $skipped = 0;
- foreach ($rows as $row) {
- if ((int)$row->batch_sms_status === 1) {
- $skipped++;
- continue;
- }
- $now = time();
- $sendResult = false;
- $responseCode = 'FAIL';
- $responseMsg = '';
- $subject = '';
- $content = '';
- try {
- if (!$row->email || !Validate::is($row->email, 'email')) {
- throw new \RuntimeException('邮箱为空或格式不正确');
- }
- $activityConfig = $this->loadActivityConfig((int)$row->activity_id, (string)$row->lang);
- if (empty($activityConfig)) {
- throw new \RuntimeException('活动配置不存在,无法发送统一邮件');
- }
- $activityTitle = trim((string)($activityConfig['title'] ?? $row->activity_title ?? ''));
- $batchTpl = trim((string)($activityConfig['batch_sms_content'] ?? ''));
- $content = $batchTpl !== ''
- ? str_replace('{title}', $activityTitle, $batchTpl)
- : 'You reserved [' . $activityTitle . ']. We have updates for you. Please stay tuned.';
- $subject = $activityTitle . ' Update Notification';
- [$sendResult, $responseCode, $responseMsg] = $this->sendAppointmentEmail($row->email, $subject, $content);
- $row->activity_title = $activityTitle;
- } catch (\Throwable $e) {
- $sendResult = false;
- $responseCode = 'EXCEPTION';
- $responseMsg = $e->getMessage();
- }
- AppointmentEmailLogModel::create([
- 'record_id' => $row->id,
- 'activity_id' => $row->activity_id,
- 'email' => $row->email,
- 'mail_type' => 'appointment_batch',
- 'subject' => $subject,
- 'content' => $content,
- 'status' => $sendResult ? 1 : 2,
- 'response_code' => $responseCode,
- 'response_msg' => $responseMsg ?: ($sendResult ? '后台批量邮件发送成功' : '后台批量邮件发送失败'),
- 'retry_count' => 0,
- 'send_time' => $sendResult ? $now : 0,
- 'createtime' => $now,
- 'updatetime' => $now,
- ]);
- $row->batch_sms_status = $sendResult ? 1 : 2;
- $row->batch_sms_time = $sendResult ? $now : $row->batch_sms_time;
- $row->updatetime = $now;
- $row->save();
- $sendResult ? $success++ : $failed++;
- }
- $this->success('统一发送邮件完成:成功 ' . $success . ' 条,失败 ' . $failed . ' 条,跳过 ' . $skipped . ' 条');
- }
- public function resendSms()
- {
- if (!$this->request->isPost()) {
- $this->error('请求方式错误');
- }
- $id = (int)$this->request->post('id/d', 0);
- if ($id <= 0) {
- $this->error('参数错误');
- }
- $row = $this->modelClass->where('id', $id)->find();
- if (!$row) {
- $this->error('预约记录不存在');
- }
- $activity = $this->loadActivityConfig((int)$row->activity_id, (string)$row->lang);
- if (empty($activity)) {
- $this->error('活动配置不存在,无法补发通知');
- }
- $activityTitle = trim((string)($activity['title'] ?? $row->activity_title ?? ''));
- $submitTpl = trim((string)($activity['submit_sms_content'] ?? ''));
- $now = time();
- if ($row->notify_channel === 'email') {
- $content = $submitTpl !== ''
- ? str_replace('{title}', $activityTitle, $submitTpl)
- : 'You have successfully reserved [' . $activityTitle . ']. We will notify you by email when updates are available.';
- $subject = $activityTitle . ' Reservation Confirmation';
- [$sendResult, $responseCode, $responseMsg] = $this->sendAppointmentEmail($row->email, $subject, $content);
- AppointmentEmailLogModel::create([
- 'record_id' => $row->id,
- 'activity_id' => $row->activity_id,
- 'email' => $row->email,
- 'mail_type' => 'appointment_resend',
- 'subject' => $subject,
- 'content' => $content,
- 'status' => $sendResult ? 1 : 2,
- 'response_code' => $responseCode,
- 'response_msg' => $responseMsg ?: ($sendResult ? '后台单条补发邮件成功' : '后台单条补发邮件失败'),
- 'retry_count' => 0,
- 'send_time' => $sendResult ? $now : 0,
- 'createtime' => $now,
- 'updatetime' => $now,
- ]);
- } else {
- if (!Event::hasListener('sms_notice')) {
- $this->error('未检测到短信通知插件监听 sms_notice');
- }
- $content = $submitTpl !== ''
- ? str_replace('{title}', $activityTitle, $submitTpl)
- : '您已成功预约【' . $activityTitle . '】,新品动态发布后我们将第一时间短信通知您。';
- $sendResult = SmsLib::notice($row->mobile, $content, null);
- AppointmentSmsLogModel::create([
- 'record_id' => $row->id,
- 'activity_id' => $row->activity_id,
- 'mobile' => $row->mobile,
- 'sms_type' => 'appointment_resend',
- 'template_code' => '',
- 'content' => $content,
- 'status' => $sendResult ? 1 : 2,
- 'response_code' => $sendResult ? 'SUCCESS' : 'FAIL',
- 'response_msg' => $sendResult ? '后台单条补发短信成功' : '后台单条补发短信失败',
- 'retry_count' => 0,
- 'send_time' => $sendResult ? $now : 0,
- 'createtime' => $now,
- 'updatetime' => $now,
- ]);
- }
- $row->activity_title = $activityTitle;
- $row->submit_sms_status = $sendResult ? 1 : 2;
- $row->submit_sms_time = $sendResult ? $now : $row->submit_sms_time;
- $row->updatetime = $now;
- $row->save();
- if ($sendResult) {
- $this->success($row->notify_channel === 'email' ? '补发邮件成功' : '补发短信成功');
- }
- $this->error($row->notify_channel === 'email' ? '补发邮件失败' : '补发短信失败');
- }
- public function del()
- {
- if (!$this->request->isPost()) {
- $this->error('请求方式错误');
- }
- $ids = $this->request->post('ids/a', []);
- if (!$ids) {
- $this->error('请先选择要删除的预约记录');
- }
- $rows = $this->modelClass->where('id', 'in', $ids)->select();
- if ($rows->isEmpty()) {
- $this->error('未找到可删除的预约记录');
- }
- Db::startTrans();
- try {
- AppointmentSmsLogModel::where('record_id', 'in', $ids)->delete();
- AppointmentEmailLogModel::where('record_id', 'in', $ids)->delete();
- $count = $this->modelClass->where('id', 'in', $ids)->delete();
- Db::commit();
- } catch (\Throwable $e) {
- Db::rollback();
- $this->error('删除失败:' . $e->getMessage());
- }
- $this->success('已删除 ' . $count . ' 条预约记录');
- }
- public function smslog()
- {
- $smsModel = new AppointmentSmsLogModel();
- if ($this->request->isAjax()) {
- [$page, $limit, $where, $sort, $order] = $this->buildTableParames();
- $mobile = trim((string)$this->request->param('mobile/s', ''));
- $smsType = trim((string)$this->request->param('sms_type/s', ''));
- $status = $this->request->param('status/s', '');
- $query = $smsModel->where($where);
- if ($mobile !== '') {
- $query->where('mobile', 'like', '%' . $mobile . '%');
- }
- if ($smsType !== '') {
- $query->where('sms_type', 'like', '%' . $smsType . '%');
- }
- if ($status !== '') {
- $query->where('status', (int)$status);
- }
- $count = $query->order($sort, $order)->count();
- $data = $query->order($sort, $order)->page($page, $limit)->select();
- return json(['code' => 0, 'count' => $count, 'data' => $data]);
- }
- $this->assign('smsLogStatusList', $smsModel->getStatusList());
- return $this->fetch('appointment/smslog');
- }
- public function emaillog()
- {
- $emailModel = new AppointmentEmailLogModel();
- if ($this->request->isAjax()) {
- [$page, $limit, $where, $sort, $order] = $this->buildTableParames();
- $email = trim((string)$this->request->param('email/s', ''));
- $recordId = (int)$this->request->param('record_id/d', 0);
- $activityId = (int)$this->request->param('activity_id/d', 0);
- $mailType = trim((string)$this->request->param('mail_type/s', ''));
- $status = $this->request->param('status/s', '');
- $sendTimeStart = trim((string)$this->request->param('send_time_start/s', ''));
- $sendTimeEnd = trim((string)$this->request->param('send_time_end/s', ''));
- $query = $emailModel->where($where);
- if ($email !== '') {
- $query->where('email', 'like', '%' . $email . '%');
- }
- if ($recordId > 0) {
- $query->where('record_id', $recordId);
- }
- if ($activityId > 0) {
- $query->where('activity_id', $activityId);
- }
- if ($mailType !== '') {
- $query->where('mail_type', 'like', '%' . $mailType . '%');
- }
- if ($status !== '') {
- $query->where('status', (int)$status);
- }
- if ($sendTimeStart !== '') {
- $query->where('send_time', '>=', strtotime($sendTimeStart));
- }
- if ($sendTimeEnd !== '') {
- $query->where('send_time', '<=', strtotime($sendTimeEnd));
- }
- $count = $query->order($sort, $order)->count();
- $data = $query->order($sort, $order)->page($page, $limit)->select();
- return json(['code' => 0, 'count' => $count, 'data' => $data]);
- }
- $this->assign('emailLogStatusList', $emailModel->getStatusList());
- return $this->fetch('appointment/emaillog');
- }
- public function delSmslog()
- {
- if (!$this->request->isPost()) {
- $this->error('请求方式错误');
- }
- $ids = $this->request->post('ids/a', []);
- if (!$ids) {
- $this->error('请先选择要删除的短信日志');
- }
- $rows = AppointmentSmsLogModel::where('id', 'in', $ids)->select();
- if ($rows->isEmpty()) {
- $this->error('未找到可删除的短信日志');
- }
- $count = AppointmentSmsLogModel::where('id', 'in', $ids)->delete();
- $this->success('已删除 ' . $count . ' 条短信日志');
- }
- public function delEmaillog()
- {
- if (!$this->request->isPost()) {
- $this->error('请求方式错误');
- }
- $ids = $this->request->post('ids/a', []);
- if (!$ids) {
- $this->error('请先选择要删除的邮件日志');
- }
- $rows = AppointmentEmailLogModel::where('id', 'in', $ids)->select();
- if ($rows->isEmpty()) {
- $this->error('未找到可删除的邮件日志');
- }
- $count = AppointmentEmailLogModel::where('id', 'in', $ids)->delete();
- $this->success('已删除 ' . $count . ' 条邮件日志');
- }
- }
|