Merge branch 'develop' into feature/mzl_dev

This commit is contained in:
mzl
2025-08-22 16:41:18 +08:00
20 changed files with 485 additions and 56 deletions
+9
View File
@@ -35,6 +35,9 @@ class UserService
/** 更新 */
public function serviceUpdateUser(Request $request, array $data = [])
{
if(isset($data['report_to']) && empty($data['report_to'])){
$data['report_to'] = 0;
}
$data = $this->preProcess('Update', $data, $request);
$config = $this->buildQueryConfig($request, 'update');
$updated = $this->logicUpdateBy($config, $data);
@@ -44,6 +47,9 @@ class UserService
/** 更新 */
public function serviceUpdate(Request $request, array $data = [])
{
if(isset($data['report_to']) && empty($data['report_to'])){
$data['report_to'] = 0;
}
unset($data['roles']);
unset($data['corp_name']);
$data = $this->preProcess('Update', $data, $request);
@@ -75,6 +81,9 @@ class UserService
$k = '%' . $p['keyword'] . '%';
$config['where']['name'] = ['like', $k];
}
if (isset($p['status']) && $p['status']) {
$config['where']['status'] = $p['status'];
}
if (isset($p['user_id']) && $p['user_id']) {
$config['where']['user_id'] = $p['user_id'];
}
+15 -7
View File
@@ -87,13 +87,21 @@ class AuthLogic
try {
$phone = $this->sanitizePhone($feishuUserInfo['mobile'] ?? '');
$email = $feishuUserInfo['enterprise_email'];
$user = User::where('corp_id', $feishuUserInfo['corp_id'])
->where(function($query) use ($phone, $email) {
$query->where('phone', $phone)
->orWhere('email', $email);
})
->first();
// $user = User::where('corp_id', $feishuUserInfo['corp_id'])
// ->where(function($query) use ($phone, $email) {
// $query->where('phone', $phone)
// ->orWhere('email', $email);
// })
// ->first();
$userByPhone = User::where('corp_id', $feishuUserInfo['corp_id'])
->where('phone', $phone)
->where('phone', '!=', '')
->first();
$userByEmail = User::where('corp_id', $feishuUserInfo['corp_id'])
->where('email', $email)
->where('email', '!=', '')
->first();
$user = $userByPhone ?: $userByEmail;
if (!$user) {
// 获取编号
$userSn = $this->getAvailableUserSn();
+49
View File
@@ -0,0 +1,49 @@
<?php
namespace app\common\model;
use support\Model;
class CustomerAudit extends Model
{
/**
* The connection name for the model.
*
* @var string|null
*/
protected $connection = 'mysql';
/**
* The table associated with the model.
*
* @var string
*/
protected $table = 'crm_customer_audit';
/**
* The primary key associated with the table.
*
* @var string
*/
protected $primaryKey = 'id';
/**
* Indicates if the model should be timestamped.
*
* @var bool
*/
public $timestamps = true;
protected $dateFormat = 'U';
/**
* 允许自动填充模型字段
*/
protected $fillable = ['id', 'customer_id', 'remark', 'img', 'audit', 'report_user_id', 'audit_user_id', 'created_at', 'updated_at'];
/**
* 不允许自动填充模型字段
*/
protected $guarded = [];
}
@@ -80,6 +80,7 @@
<li>工单编号:{{code}}</li>
<li>工单分类:{{category}}</li>
<li>问题描述:{{content}}</li>
{{reply}}
</ul>
<p>请点击下方按钮立即查看详情:</p>
+15 -9
View File
@@ -50,6 +50,7 @@ class CustomerController extends BaseController
: null);
foreach ($data['records'] as &$item) {
$item = $this->service->getCustomer($item);
$item = Util::formatDate($item,['created_at','updated_at']);
}
return $this->success($data);
} catch (\Throwable $e) {
@@ -162,7 +163,7 @@ class CustomerController extends BaseController
$perPage = $request->input('size', 10);
$where = [
['user_id', '=', $userId],
['corp_abbr', '=', $request->basic_data['corp_abbr']],
// ['corp_abbr', '=', $request->basic_data['corp_abbr']],
['follow_next', '<>', 0],
];
@@ -239,6 +240,9 @@ class CustomerController extends BaseController
if (Util::isEmpty($param['id'])) {
return $this->error(trans('id_empty'));
}
if (empty($param['remark']) && empty($param['img'])) {
return $this->error('举报理由不能为空');
}
$param['user_id'] = $request->user->uid;
$param['corp_abbr'] = $request->basic_data['corp_abbr'];
@@ -326,6 +330,7 @@ class CustomerController extends BaseController
'address' => Util::getParam($request, 'address', ''),
'sex' => Util::getParam($request, 'sex', 0),
'obtain' => time(),
'company' => Util::getParam($request, 'company', 0),
];
if (Util::isEmpty($id)) {
@@ -383,7 +388,7 @@ class CustomerController extends BaseController
public function delete(Request $request)
{
$id = Util::getParam($request, 'id');
$force = Util::getParam($request, 'force','');
$scene = Util::getParam($request, 'scene','');
$userId = $request->user->uid;
$where = [
@@ -396,10 +401,11 @@ class CustomerController extends BaseController
}
try {
Db::beginTransaction();
if ($force == 'force') {
//强制删除
$res = $customer->forceDelete();
} else {
if ($scene == 'force') {
//status=5:业务员自己删除
$customer->status = 5;
$res = $customer->save();
}else{
$customer->user_id = 0;
$customer->save();
@@ -409,10 +415,10 @@ class CustomerController extends BaseController
'user_his' => $userId,
'user_id' => 0,
]);
//软删除
$res = $customer->delete();
}
//软删除
$res = $customer->delete();
Db::commit();
} catch (\Throwable $e) {
Db::rollback();
+16 -9
View File
@@ -36,15 +36,22 @@ class Follow extends Model
*
* @var bool
*/
public $timestamps = true;
public $timestamps = false;
protected $dates = ['created_at', 'updated_at', 'follow_time'];
/**
* 在保存时手动设置时间戳
*/
protected static function boot()
{
parent::boot();
protected $casts = [
'updated_at' => 'datetime:Y-m-d H:i:s', // 指定序列化格式
'created_at' => 'datetime:Y-m-d H:i:s', // 指定序列化格式
'follow_time' => 'datetime:Y-m-d H:i:s', // 指定序列化格式
// 'updated_at' => 'timestamp', // 指定序列化格式
// 'created_at' => 'timestamp', // 指定序列化格式
];
static::creating(function ($model) {
$model->created_at = time();
$model->updated_at = time();
});
static::updating(function ($model) {
$model->updated_at = time();
});
}
}
+45 -4
View File
@@ -3,18 +3,23 @@
namespace app\crm\service;
use app\common\model\Corp;
use app\common\model\CustomerAudit;
use app\common\model\User;
use app\common\traits\crud\CrudServiceTrait;
use app\crm\logic\CustomerLogic;
use app\crm\model\Channel;
use app\crm\model\Country;
use app\crm\model\Customer;
use app\crm\model\Tag;
use app\crm\model\CustomerHis;
use app\crm\model\Follow;
use app\crm\utils\Util;
use config\constants\Constants;
use support\Request;
/**
* @method mixed complexQuery(array $params)
*/
class CustomerService
{
@@ -36,6 +41,8 @@ class CustomerService
$follow = $params['follow'] ?? '';
$follow_last = $params['follow_last'] ?? '';
$tagId = $params['tag_id'] ?? [];
$sort = $params['sort'] ?? null;
$sortId = $params['sort_id'] ?? null;
$countryId = $params['country_id'] ?? '';
$where = [];
$user_id =$params['user_id'];
@@ -71,7 +78,7 @@ class CustomerService
$where[] = ['follow_last', '>', strtotime('-7 day')];
}
$query = Customer::where($where);
$query = Customer::select('crm_customer.*')->where($where);
if(!empty($tagId)){
//查询有$tagId 里任意一个标签的客户
@@ -114,7 +121,33 @@ class CustomerService
$query->withTrashed();
}
$customer = $query->orderBy('id','desc')->paginate($perPage, ['*'], 'page', $page);
if ($sort == 'tag_group') {
// 排序:按关联的 crm_tag.sort 最小值升序,其次按客户ID倒序
$minSortSub = Tag::selectRaw('MIN(crm_tag.sort) AS min_sort, crm_customer_tag.customer_id')
->join('crm_customer_tag', 'crm_customer_tag.tag_id', '=', 'crm_tag.id')
->whereNull('crm_tag.deleted_at')
->when(!empty($sortId), function ($q) use ($sortId) {
$q->where('crm_tag.group_id', $sortId);
})
->groupBy('crm_customer_tag.customer_id');
$query->leftJoinSub($minSortSub, 'tag_min', function ($join) {
$join->on('crm_customer.id', '=', 'tag_min.customer_id');
});
$query = $query->orderByRaw('tag_min.min_sort IS NULL')
->orderBy('tag_min.min_sort', 'asc')
->orderBy('crm_customer.id', 'desc');
}elseif ($sort == 'follow_last') {
$query = $query->orderBy('crm_customer.follow_last', 'desc');
}elseif ($sort == 'follow_next') {
$query = $query->orderByRaw('crm_customer.follow_next IS NULL, crm_customer.follow_next ASC');
}elseif ($sort == 'id' || empty($sort)) {
$query = $query->orderBy('crm_customer.id', 'desc');
}
$customer = $query->paginate($perPage, ['*'], 'page', $page);
foreach ($customer as &$item) {
$item = $this->getCustomer($item);
if($seas == 'seas'){
@@ -195,6 +228,14 @@ class CustomerService
return false;
}
CustomerAudit::create([
'customer_id' => $id,
'report_user_id' => $userId,
'remark' => $params['remark'],
'status' => 1,
'img' => implode(',', $params['img']),
]);
CustomerHis::create([
'customer_id' => $id,
'user_his' => $userId,
@@ -247,7 +288,7 @@ class CustomerService
// $customer['created_at'] = Util::timeTotDate($customer['created_at']);
// $customer['updated_at'] = Util::timeTotDate($customer['updated_at']);
$customer = Util::formatDate($customer,['follow_last']);
$customer = Util::formatDate($customer,['follow_next','follow_last']);
$nameLang = $language=='en'?'name_en':($language=='ru'?'name_ru':'name');
$countryLang = $language=='en'?'en_addr':'cn_addr';
// $customer['car_type_name'] = empty($customer['car_type_id'])?'':CarType::where(['id'=>$customer['car_type_id']])->value($nameLang);
@@ -272,7 +313,7 @@ class CustomerService
public function detail($params)
{
$id =$params['id'];
$customer = Customer::with('tags')->select('id', 'user_id', 'grade', 'channel_id', 'car_type_id', 'country_id', 'magnitude', 'email', 'phone', 'WhatsApp', 'contacts', 'describe', 'address', 'lat', 'lng', 'follow_next', 'follow_remark', 'sex')
$customer = Customer::with('tags')->select('id', 'user_id', 'grade', 'channel_id', 'car_type_id', 'country_id', 'magnitude', 'email', 'phone', 'WhatsApp', 'contacts', 'describe', 'address', 'lat', 'lng', 'follow_next', 'follow_remark', 'sex', 'company')
->where('id', $id)
->first();
+3
View File
@@ -59,6 +59,9 @@ class FollowService
$oss_picture = $ossservice->generatePrivateUrl($follow['picture'], 86400);
}
$follow['picture_full'] = $oss_picture;
$follow = Util::formatDate($follow,['created_at','updated_at','follow_time']);
$follow['follow_time'] = empty($follow['follow_time'])?'':$follow['follow_time'];
// $follow = Util::formatDate($follow);
return $follow;
}
+7 -1
View File
@@ -100,7 +100,13 @@ class Util
public static function formatDate($value,$key = ['created_at','updated_at'])
{
foreach ($key as $k){
$value[$k]= self::timeTotDate($value[$k]);
// 如果是整数,可能是 UNIX 时间戳
if (is_numeric($value[$k]) && $value[$k] > 0) {
// 检查是否是合理的时间戳范围(1970-2100年)
if ($value[$k] >= 0 && $value[$k] <= 4102444800) {
$value[$k]= self::timeTotDate($value[$k]);
}
}
}
return $value;
}
+65 -10
View File
@@ -4,6 +4,7 @@ namespace app\crmAdmin\controller;
use app\common\model\Corp;
use app\crm\model\Customer;
use app\crm\utils\Util;
use app\crmAdmin\service\CustomerService;
use support\Request;
@@ -85,7 +86,7 @@ class CustomerController extends BaseController
}
/**
* 客户列表
* 审核客户
* @param Request $request
* @return \support\Response
*/
@@ -147,17 +148,19 @@ class CustomerController extends BaseController
return $this->error('customer_id'.trans('not_null'));
}
$where = [
'id' => $param['customer_id'],
];
$customer = Customer::where($where)->withTrashed()->first();
if(empty($customer)){
$customer_id = explode(',', $param['customer_id']);
$query = Customer::whereIn('id',$customer_id)->withTrashed();
if(!$query->exists()){
return $this->error( trans('fail'));
}
//软删除
$customer->status = 3;
$res = $customer->save();
$customer->delete();
$scene = $param['scene'] ?? '';
if ($scene === 'list') { //管理端客户列表移除
$res = $query->update(['status' => 4, 'deleted_at' => time()]);
} elseif ($scene === 'force') { //强删除
$res = $query->forceDelete();
} else { //公海软删除
$res = $query->update(['status' => 3, 'deleted_at' => time()]);
}
return $this->success($res);
} catch (\Throwable $th) {
@@ -165,6 +168,34 @@ class CustomerController extends BaseController
}
}
/**
* 客户恢复
* @param Request $request
* @return \support\Response
*/
public function restore(Request $request)
{
try {
$id = $request->input('id', '');
if (Util::isEmpty($id)) {
return $this->error(trans('id_empty'));
}
$ids = explode(',', $id);
$query = Customer::withTrashed()->whereIn('id', $ids);
if (!$query->exists()) {
return $this->error(trans('fail'));
}
// 恢复软删除(清空 deleted_at)
$query->restore();
// 恢复为在库状态,放入公海
$res = Customer::whereIn('id', $ids)->update(['status' => 1, 'user_id' => 0]);
return $this->success($res, trans('success'));
} catch (\Throwable $th) {
return $this->error($th->getMessage());
}
}
/**
* 客户详情
* @param Request $request
@@ -207,4 +238,28 @@ class CustomerController extends BaseController
}
}
/**
* 离职员工客户分配
* @param Request $request
* @return \support\Response
*/
public function allocation(Request $request)
{
try {
$param = $request->all();
if (empty($param['corp_id'])) {
return $this->error('corp_id'.trans('not_null'));
}
if (empty($param['user_id'])) {
return $this->error('user_id'.trans('not_null'));
}
$result = (new CustomerService())->allocation($param);
return $this->success($result,'成功分配'.$result['userCount'].'位离职用户的'.$result['customerCount'].'位客户');
} catch (\Throwable $th) {
return $this->error($th->getMessage());
}
}
}
+1
View File
@@ -17,6 +17,7 @@ class CustomerLogic
$customer->restore();
}
return $res;
}
+97 -5
View File
@@ -2,6 +2,7 @@
namespace app\crmAdmin\service;
use app\common\model\CustomerAudit;
use app\common\model\InquiryLog;
use app\common\model\User;
use app\common\service\OssService;
@@ -20,6 +21,8 @@ use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Style\Border;
use PhpOffice\PhpSpreadsheet\Style\Fill;
use support\Db;
use support\exception\BusinessException;
use support\Log;
class CustomerService
{
@@ -48,12 +51,14 @@ class CustomerService
$follow_last = $params['follow_last'] ?? '';
$tagId = $params['tag_id'] ?? [];
$user_id = $params['user_id'] ?? '';
$seas = $params['seas'] ?? '';
$seas = $params['seas'] ?? ''; //recyclea:管理端回收站,audit:待审核列表,seas:公海
$scene = $params['scene'] ?? '';
$where = [];
if ($scene == 'audit') {
$where[] = ['status', '=', 2];
} elseif ($scene == 'recyclea') {
$where[] = ['status', '>', 2];
} else {
$where[] = ['status', '=', 1];
}
@@ -118,8 +123,8 @@ class CustomerService
if ($recycle == 'recycle' || $scene == 'recycle' || $scene == 'audit') {
$query->onlyTrashed();
}
if ($seas == 'seas' || $scene == 'seas') {
$query->withTrashed();
if ($seas == 'seas' || $scene == 'recyclea') {
$query = $query->withTrashed();
}
if (!$export) {
@@ -132,13 +137,31 @@ class CustomerService
foreach ($customer as &$item) {
$item = $this->getCustomer($item);
$item['desc_collect'] = $item['desc_collect'] ?? '';
$item['follow_next'] = empty($item['follow_next'])?'':date('Y-m-d H:i:s', $item['follow_next']);
if ($seas == 'seas' || $scene == 'seas') {
$item['seas_time'] = time() - (empty($item['deleted_at'])?strtotime($item['updated_at']):strtotime($item['deleted_at']));
}
if ($scene == 'audit') { //审核时查询举报人姓名
$customerHis = CustomerHis::where('customer_id', $item->id)->orderBy('id', 'desc')->first(['user_his']);
$item['user_name'] = empty($customerHis['user_his']) ? '' : User::where('id',$customerHis['user_his'])->value('name');
$audit = CustomerAudit::where('customer_id', $item->id)->orderBy('id', 'desc')->first();
if (!empty($audit)&&!empty($audit['img'])) {
$audit = $audit?$audit->toArray():'';
$audit['img'] = explode(',', $audit['img']);
$ossservice = new OssService();
foreach ($audit['img'] as $k => $img) {
$audit['img'][$k] = $ossservice->generatePrivateUrl($img);
}
}
$item['audit'] = $audit;
}
if ($scene == 'recyclea' && $item['status'] == 3) { //回收站删除来源
$item['del_source'] = '公海';
}elseif ($scene == 'recyclea' && $item['status'] == 4) {
$item['del_source'] = '管理端';
}elseif ($scene == 'recyclea' && $item['status'] == 5) {
$source = (!empty($item['user_id'])) ? (':' . User::where('id',$item['user_id'])->value('name')) : '';
$item['del_source'] = '业务员' . $source;
}
}
}
@@ -287,9 +310,18 @@ class CustomerService
$id = $params['id'];
$logic = new CustomerLogic();
$audit = CustomerAudit::where('customer_id', $id)->orderBy('id', 'desc')->first();
if ($params['scene'] == 'delete') {
if(!empty($audit)){
$audit->status = 3;
$audit->save();
}
return $logic->forceDelete($params['id']);
} else {
if(!empty($audit)){
$audit->status = 2;
$audit->save();
}
return $logic->status($params['id'], 1);
}
}
@@ -404,7 +436,7 @@ class CustomerService
// $customer['created_at'] = Util::timeTotDate($customer['created_at']);
// $customer['updated_at'] = Util::timeTotDate($customer['updated_at']);
$customer = Util::formatDate($customer, ['follow_last']);
$customer = Util::formatDate($customer, ['follow_next','follow_last']);
$nameLang = $language == 'en' ? 'name_en' : ($language == 'ru' ? 'name_ru' : 'name');
$countryLang = $language == 'en' ? 'en_addr' : 'cn_addr';
// $customer['car_type_name'] = empty($customer['car_type_id'])?'':CarType::where(['id'=>$customer['car_type_id']])->value($nameLang);
@@ -447,9 +479,69 @@ class CustomerService
$ossservice = new OssService();
foreach ($follow as $item) {
$item = Util::formatDate($item,['created_at','updated_at','follow_time']);
$item['follow_time'] = empty($item['follow_time'])?'':$item['follow_time'];
$item['picture_full'] = empty($item->picture)?'':$ossservice->generatePrivateUrl($item->picture);
}
return $follow;
}
/**
* 离职员工客户分配
* @param $params
* @return string[]
*/
public function allocation($params)
{
$corpId = $params['corp_id'];
$userId = explode(',', $params['user_id']);
log::info('开始分配离职员工客户,corp_id:'.$corpId.' 被分配员工'. implode(',', $userId));
//查询离职客户
$userResign = User::where('status', 2)
->where('corp_id', $corpId)
->get(['id','name']);
$resignUerIds = [];
$userNames = [];
foreach ($userResign as $row) {
$resignUerIds[] = (int)$row->id;
$userNames[] = $row->name;
}
if (empty($userResign)) {
log::info('未匹配到离职用户');
throw new BusinessException('未匹配到离职用户', 500);
}
log::info('匹配到离职用户数:' . count($resignUerIds) .' '. implode(',',$userNames));
$customerCount = Customer::whereIn('user_id', $resignUerIds)
->orderBy('id', 'asc')
->count();
if ($customerCount === 0) {
log::info('未找到离职员工相关的客户记录。');
throw new BusinessException('未找到离职员工相关的客户记录', 500);
}
// 初始化 UID 轮询器
$uidRotator = new \app\common\utils\RedisUidRotator('allocation_customer_user');
$uidRotator->setUids($userId, false);
Customer::whereIn('user_id',$resignUerIds)->chunk(500, function ($customers) use ($uidRotator){
foreach ($customers as $customer) {
// 获取下一个分配的UID
$newUserId = $uidRotator->next();
$customer->user_id = $newUserId;
$customer->save();
}
});
return [
'userCount' => count($resignUerIds),
'customerCount' => $customerCount,
];
}
}
@@ -31,6 +31,24 @@ class ConversationController extends BaseController
return $this->error($th->getMessage());
}
}
/**
* 工单邮件补发
* @param Request $request
* @return \support\Response
*/
public function sendEmail(Request $request)
{
try {
$res = (new ConversationService())->sendEmail($request->all());
return $res
? $this->success($res)
: $this->error();
} catch (\Throwable $th) {
return $this->error($th->getMessage());
}
}
public function edit(Request $request)
{
try {
+8
View File
@@ -23,6 +23,14 @@ class CategorieLogic
return Categorie::with('translation')->where($where)->get();
}
public function find($id)
{
return Categorie::with(['translation' => function ($query) {
$query->where('locale', locale());
}])->where('status', 1)
->find($id);
}
public function add(array $data)
{
try {
+14
View File
@@ -18,6 +18,7 @@ class ConversationLogic
$current = $params['current'] ?? 1;
return Conversation::where($where)->paginate($size, ['*'], 'page', $current);
}
public function add(array $data)
{
try {
@@ -43,4 +44,17 @@ class ConversationLogic
throw new BusinessException('会话编辑失败,请稍后重试', 500);
}
}
/**
* 获取工单最新一条记录
* @param array $data
* @return Conversation|\Illuminate\Database\Eloquent\Model|object|null
*/
public function firstByTicket(int $ticketId)
{
$conversation = Conversation::where('ticket_id',$ticketId)
->orderBy('id','desc')
->first();
return $conversation;
}
}
+1 -5
View File
@@ -20,11 +20,7 @@ class Conversation extends Model
protected $primaryKey = 'id';
public $timestamps = true;
protected $dateFormat = 'U';
protected $dates = ['created_at', 'updated_at'];
protected $casts = [
'updated_at' => 'datetime:Y-m-d H:i:s',
'created_at' => 'datetime:Y-m-d H:i:s',
];
protected $fillable = [
'ticket_id',
'user_id',
+24 -6
View File
@@ -47,16 +47,34 @@ class Ticket extends Model
*
* @var bool
*/
public $timestamps = true;
public $timestamps = false;
protected $dateFormat = 'U';
protected $dates = ['created_at', 'updated_at'];
/**
* 在保存时手动设置时间戳
*/
protected static function boot()
{
parent::boot();
protected $casts = [
'updated_at' => 'datetime:Y-m-d H:i:s', // 指定序列化格式
'created_at' => 'datetime:Y-m-d H:i:s', // 指定序列化格式
];
static::creating(function ($model) {
$model->created_at = time();
$model->updated_at = time();
});
static::updating(function ($model) {
$model->updated_at = time();
});
}
/**
* 指定哪些字段自动转换为 Carbon 实例
*/
public function getDates()
{
return [];
}
protected $fillable = [
'code',
@@ -4,7 +4,10 @@ namespace app\ticket\service;
use app\common\model\User;
use app\common\service\OssService;
use app\ticket\logic\CategorieLogic;
use app\ticket\logic\ConversationLogic;
use app\ticket\logic\TicketLogic;
use app\ticket\model\Conversation;
use config\constants\Constants;
use support\Db;
use support\exception\BusinessException;
@@ -32,6 +35,8 @@ class ConversationService
$user = User::where('id', $value['user_id'])->first();
$value['user_name'] = $user?->name;
$value['user_avatar'] = $user?->avatar;
$value['created_at'] = date('Y-m-d H:i:s', strtotime($value['created_at']));
$value['updated_at'] = date('Y-m-d H:i:s', strtotime($value['updated_at']));
$result[$key] = $value;
}
return $result;
@@ -44,12 +49,96 @@ class ConversationService
if (empty($data['content'])) {
throw new BusinessException('消息内容不能为空');
}
$conversation = (new ConversationLogic())->firstByTicket($data['ticket_id']);
$ticket = (new TicketLogic())->find($data['ticket_id']);
$categorie= (new CategorieLogic())->find($ticket['categorie_id']);
$categorieName = isset($categorie['translation']) ? $categorie['translation']['name'] : '';
$notice = [
'code' => $ticket['code'],
'category' => $categorieName,
'content' => $data['content'],
'reply' => '',
];
//$emailDefault = 'app@hnxinyouhe.com'; //公共邮箱
//$emailDefault = 'support@hnxinyouhe.com'; //公共邮箱
$emailDefault = env('TICKET_EMAIL_DEFAULT');
if (empty($conversation)) {
$email = $emailDefault;
}else{
$tiket = (new TicketLogic())->find($conversation['ticket_id']);
if($data['user_id'] != $tiket['user_id']){
$email = User::where('id',$tiket['user_id'])->value('email');
}else{
$conversationLast = Conversation::where('ticket_id', '=', $conversation['ticket_id'])
->where('user_id', '!=', $data['user_id'])
->orderBy('id', 'desc')
->first();
$email = (!empty($conversationLast['user_id']))?User::where('id',$conversationLast['user_id'])->value('email',$emailDefault):$emailDefault;
}
$notice['content'] = $tiket['content'];
$status_fanyi = array_map(fn($v) => "{{{$v}}}", array_flip(Constants::TICKET_STATUS));
$locale = locale();
$ticket_status = $locale == 'zh'? Constants::TICKET_STATUS_ZH:Constants::TICKET_STATUS_EN;
$content = str_replace($status_fanyi,$ticket_status,$data['content']);
$notice['reply'] = '<li>最新回复:' . $content . '</li>';
}
if(!empty($emailDefault)){
\app\common\utils\email\MailSend::send($email, '【XYH】新的工单提醒', replaceTpl($notice, 'work_order'));
}
unset($data['categorie_id']);
unset($data['code']);
return (new ConversationLogic())->add($data);
} catch (\Throwable $e) {
throw $e;
}
}
public function sendEmail(array $data)
{
$conversation = (new ConversationLogic())->firstByTicket($data['ticket_id']);
$ticket = (new TicketLogic())->find($data['ticket_id']);
$categorie= (new CategorieLogic())->find($ticket['categorie_id']);
$categorieName = isset($categorie['translation']) ? $categorie['translation']['name'] : '';
$notice = [
'code' => $ticket['code'],
'category' => $categorieName,
'content' => $ticket['content'],
'reply' => '',
];
//$emailDefault = 'app@hnxinyouhe.com'; //公共邮箱
//$emailDefault = 'support@hnxinyouhe.com'; //公共邮箱
$emailDefault = env('ticket_email_default');
if (empty($conversation)) {
$email = $emailDefault;
}else{
$tiket = (new TicketLogic())->find($conversation['ticket_id']);
if($conversation['user_id'] != $tiket['user_id']){
$email = User::where('id',$tiket['user_id'])->value('email');
}else{
$conversationLast = Conversation::where('ticket_id', '=', $conversation['ticket_id'])
->where('user_id', '!=', $conversation['user_id'])
->orderBy('id', 'desc')
->first();
$email = (!empty($conversationLast['user_id']))?User::where('id',$conversationLast['user_id'])->value('email',$emailDefault):$emailDefault;
}
$notice['content'] = $tiket['content'];
// $notice['reply'] = '<li>最新回复:' . $conversation['content'] . '</li>';
$notice['reply'] = '<li>最新回复:' . '卡罗拉、极石01、比亚迪唐,宋Plus、丰田荣放、捷途T2、极氪7x、(阿联酋, 亚美尼亚, 阿塞拜疆, 白俄罗斯, 哥斯达黎加, 埃塞俄比亚, 格鲁吉亚, 加纳, 吉尔吉斯斯坦, 蒙古, 巴拉圭, 沙特阿拉伯, 塔吉克斯坦, 土库曼斯坦, 乌兹别克斯坦,委内瑞拉)起亚亦跑(阿尔及利亚),基本上每个车都推中亚中东南美非洲' . '</li>';
}
\app\common\utils\email\MailSend::send($email, '【XYH】新的工单提醒', replaceTpl($notice, 'work_order'));
return $email;
}
public function edit(array $data)
{
try {
+5
View File
@@ -33,6 +33,8 @@ class TicketService
$user = User::where('id', $v['user_id'])->first();
$res[$k]['user_name'] = $user?->name;
$res[$k]['user_avatar'] = $user?->avatar;
$res[$k]['created_at'] = date('Y-m-d H:i:s', $v['created_at']);
$res[$k]['updated_at'] = date('Y-m-d H:i:s', $v['updated_at']);
}
unset($v);
unset($attachments);
@@ -45,6 +47,7 @@ class TicketService
try {
$attachment = $data['attachment']??[];
$logic = new TicketLogic();
$data['code'] = $logic::generateSimpleTicketNo();
$result = $logic->add($data);
if(!empty($attachment)){
(new AttachmentLogic())->adds($attachment, $result->id, $data['user_id']);
@@ -53,6 +56,8 @@ class TicketService
$cleanContent = trim(preg_replace('/\s+/', ' ', strip_tags($data['content'] ?? '')));
$conversation = [
'ticket_id' => $result->id,
'categorie_id' => $data['categorie_id'],
'code' => $data['code'],
'content' => $cleanContent,
'user_id' => $data['user_id'],
'attachment' => $data['attachment'],
+3
View File
@@ -176,8 +176,10 @@ Route::group('/admin', function () {
Route::any('/transfer', [app\crmAdmin\controller\CustomerController::class, 'transfer']);
Route::any('/detail', [app\crmAdmin\controller\CustomerController::class, 'detail']);
Route::any('/delete', [app\crmAdmin\controller\CustomerController::class, 'delete']);
Route::any('/restore', [app\crmAdmin\controller\CustomerController::class, 'restore']); //恢复客户
Route::any('/cede', [app\crm\controller\CustomerController::class, 'cede']);
Route::any('/follow', [app\crmAdmin\controller\CustomerController::class, 'follow']);
Route::any('/allocation', [app\crmAdmin\controller\CustomerController::class, 'allocation']);
});
});
});
@@ -197,6 +199,7 @@ Route::group('/ticket', function () {
//工单沟通记录
Route::any('/conversation/add', [app\ticket\controller\ConversationController::class, 'add']);
Route::any('/conversation/sendEmail', [app\ticket\controller\ConversationController::class, 'sendEmail']);
Route::any('/conversation/edit', [app\ticket\controller\ConversationController::class, 'edit']);
Route::any('/conversation/list', [app\ticket\controller\ConversationController::class, 'index']);