登录
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace app\ticket\controller;
|
||||
|
||||
use app\ticket\service\TicketService;
|
||||
use support\Request;
|
||||
|
||||
class AttachmentController extends BaseController
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace app\ticket\controller;
|
||||
|
||||
use support\Request;
|
||||
use support\Response;
|
||||
use support\exception\BusinessException;
|
||||
use app\common\traits\ResponseTrait;
|
||||
use think\Validate;
|
||||
|
||||
abstract class BaseController
|
||||
{
|
||||
use ResponseTrait;
|
||||
|
||||
protected mixed $validator = null;
|
||||
|
||||
/**
|
||||
* 验证数据
|
||||
*
|
||||
* @param Validate $validator 验证器实例
|
||||
* @param array $data 待验证的数据
|
||||
* @param string $scene 验证场景
|
||||
* @return array 验证后的数据
|
||||
* @throws BusinessException 验证失败时抛出业务异常
|
||||
*/
|
||||
public function validate(Validate $validator, array $data, string $scene = ''): array
|
||||
{
|
||||
// 如果指定了验证场景,并且验证器支持场景方法,则设置验证场景
|
||||
if ($scene && method_exists($validator, 'scene')) {
|
||||
$validator->scene($scene);
|
||||
}
|
||||
// 执行数据验证
|
||||
if (!$validator->check($data)) {
|
||||
// 验证失败,抛出业务异常,异常信息为验证器返回的错误信息
|
||||
throw new BusinessException($validator->getError());
|
||||
}
|
||||
// 验证成功,返回原始数据
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function page($result){
|
||||
$current = $result->currentPage();
|
||||
$total = $result->total();
|
||||
$size = $result->perPage();
|
||||
$result = $result->toArray();
|
||||
$result['current'] = $current;
|
||||
$result['total'] = $total;
|
||||
$result['size'] = $size;
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace app\ticket\controller;
|
||||
|
||||
use app\ticket\service\CategorieService;
|
||||
use support\Request;
|
||||
|
||||
class CategorieController extends BaseController
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
try {
|
||||
$result = (new CategorieService())->list($request->all());
|
||||
return $this->success($this->page($result));
|
||||
} catch (\Throwable $e) {
|
||||
return $this->error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function getAll(Request $request)
|
||||
{
|
||||
try {
|
||||
$result = (new CategorieService())->getAll($request->all());
|
||||
return $this->success($result);
|
||||
} catch (\Throwable $e) {
|
||||
return $this->error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function add(Request $request)
|
||||
{
|
||||
try {
|
||||
return (new CategorieService())->add($request->all())
|
||||
? $this->success()
|
||||
: $this->error();
|
||||
} catch (\Throwable $th) {
|
||||
return $this->error($th->getMessage().' '.$th->getLine().' '.$th->getFile());
|
||||
}
|
||||
}
|
||||
|
||||
public function edit(Request $request)
|
||||
{
|
||||
try {
|
||||
$result = (new CategorieService())->edit($request->all());
|
||||
return $result
|
||||
? $this->success($result)
|
||||
: $this->error();
|
||||
} catch (\Throwable $th) {
|
||||
return $this->error($th->getMessage().' '.$th->getLine().' '.$th->getFile());
|
||||
}
|
||||
}
|
||||
|
||||
public function delete(Request $request)
|
||||
{
|
||||
try {
|
||||
$result = (new CategorieService())->delete($request->input('id'));
|
||||
return $result
|
||||
? $this->success($result)
|
||||
: $this->error();
|
||||
} catch (\Throwable $th) {
|
||||
return $this->error($th->getMessage().' '.$th->getLine().' '.$th->getFile());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace app\ticket\controller;
|
||||
|
||||
use app\ticket\service\ConversationService;
|
||||
use support\Request;
|
||||
|
||||
class ConversationController extends BaseController
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
try {
|
||||
$ticket_id = $request->input('ticket_id');
|
||||
if(empty($ticket_id)){
|
||||
return $this->error('ticket_id不能为空');
|
||||
}
|
||||
$result = (new ConversationService())->list($request->all());
|
||||
return $this->success($this->page($result));
|
||||
} catch (\Throwable $e) {
|
||||
return $this->error($e->getMessage().$e->getLine().$e->getFile());
|
||||
}
|
||||
}
|
||||
public function add(Request $request)
|
||||
{
|
||||
try {
|
||||
$request->setPost('user_id', $request->user->uid);
|
||||
return (new ConversationService())->add($request->all())
|
||||
? $this->success()
|
||||
: $this->error();
|
||||
} catch (\Throwable $th) {
|
||||
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 {
|
||||
$request->setPost('user_id', $request->user->uid);
|
||||
$result = (new ConversationService())->edit($request->all());
|
||||
return $result
|
||||
? $this->success($result)
|
||||
: $this->error();
|
||||
} catch (\Throwable $th) {
|
||||
return $this->error($th->getMessage().' '.$th->getLine().' '.$th->getFile());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace app\ticket\controller;
|
||||
|
||||
use app\ticket\service\TicketService;
|
||||
use support\Request;
|
||||
|
||||
class TicketController extends BaseController
|
||||
{
|
||||
|
||||
public function index(Request $request)
|
||||
{
|
||||
try {
|
||||
$result = (new TicketService())->list($request->all());
|
||||
return $this->success($this->page($result));
|
||||
} catch (\Throwable $e) {
|
||||
return $this->error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 我的工单
|
||||
* @param Request $request
|
||||
* @return \support\Response
|
||||
*/
|
||||
public function self(Request $request)
|
||||
{
|
||||
try {
|
||||
$request->setGet('user_id',$request->user->uid);
|
||||
$result = (new TicketService())->list($request->all());
|
||||
return $this->success($result);
|
||||
// return $this->success($this->page($result));
|
||||
} catch (\Throwable $e) {
|
||||
return $this->error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function add(Request $request)
|
||||
{
|
||||
try {
|
||||
$request->setPost('user_id', $request->user->uid);
|
||||
|
||||
return (new TicketService())->add($request->all())
|
||||
? $this->success()
|
||||
: $this->error();
|
||||
} catch (\Throwable $th) {
|
||||
return $this->error($th->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function edit(Request $request)
|
||||
{
|
||||
try {
|
||||
$request->setPost('user_id', $request->user->uid);
|
||||
$result = (new TicketService())->edit($request->all());
|
||||
return $result
|
||||
? $this->success($result)
|
||||
: $this->error();
|
||||
} catch (\Throwable $th) {
|
||||
return $this->error($th->getMessage());
|
||||
}
|
||||
}
|
||||
public function status(Request $request)
|
||||
{
|
||||
try {
|
||||
$request->setPost('user_id', $request->user->uid);
|
||||
$result = (new TicketService())->status($request->all());
|
||||
return $result
|
||||
? $this->success($result)
|
||||
: $this->error();
|
||||
} catch (\Throwable $th) {
|
||||
return $this->error($th->getMessage());
|
||||
}
|
||||
}
|
||||
public function getStatus(Request $request)
|
||||
{
|
||||
try {
|
||||
$request->setGet('user_id', $request->user->uid);
|
||||
$result = (new TicketService())->getStatus($request->all());
|
||||
return $result
|
||||
? $this->success($result)
|
||||
: $this->error();
|
||||
} catch (\Throwable $th) {
|
||||
return $this->error($th->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace app\ticket\logic;
|
||||
|
||||
use app\common\model\UserTokenLog;
|
||||
use app\common\model\Systems;
|
||||
use app\common\model\User;
|
||||
use app\common\model\UserSn;
|
||||
use app\common\utils\Jwt;
|
||||
use app\ticket\model\Attachment;
|
||||
use app\ticket\model\Ticket;
|
||||
use support\Redis;
|
||||
use support\exception\BusinessException;
|
||||
use support\Log;
|
||||
|
||||
class AttachmentLogic
|
||||
{
|
||||
public function adds(array $data,int $ticket_id,int $user_id)
|
||||
{
|
||||
try {
|
||||
foreach ($data as $k=>$v){
|
||||
$v['ticket_id'] = $ticket_id;
|
||||
$v['user_id'] = $user_id;
|
||||
$res = Attachment::create($v);
|
||||
}
|
||||
return $res;
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('工单创建失败', [
|
||||
'data' => $data,
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
throw new BusinessException('工单创建失败,请稍后重试', 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function edit(array $data,int $ticket_id,int $user_id)
|
||||
{
|
||||
try {
|
||||
$attachmentsId = [];
|
||||
foreach ($data as $k=>$v){
|
||||
$v['ticket_id'] = $ticket_id;
|
||||
$v['user_id'] = $user_id;
|
||||
if(!empty($v['id'])){ //修改附件
|
||||
$attachmentId = $v['id'];
|
||||
$attachmentsId[] = $attachmentId;
|
||||
// $v_res = Attachment::update($attachmentId, $v);
|
||||
$v_res = Attachment::updateOrCreate(['id' => $v['id']],$v);
|
||||
if (!$v_res) {
|
||||
throw new BusinessException('附件保存失败');
|
||||
}
|
||||
} else { //新增附件
|
||||
unset($v['id']);
|
||||
$v_res = Attachment::create($v);
|
||||
if (!$v_res) {
|
||||
throw new BusinessException('附件创建失败');
|
||||
}
|
||||
$vId = $v_res->id;
|
||||
$attachmentsId[] = $vId;
|
||||
}
|
||||
}
|
||||
|
||||
//删除本次没有出现的附件
|
||||
$res = Attachment::whereNotIn('id', $attachmentsId)->where('ticket_id',$ticket_id)->delete();
|
||||
return $res;
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('工单编辑(附件)失败', [
|
||||
'data' => $data,
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
throw new BusinessException('工单编辑失败,请稍后重试', 500);
|
||||
}
|
||||
}
|
||||
|
||||
public static function generateSimpleTicketNo(): string
|
||||
{
|
||||
$date = date('Ymd'); // 日期
|
||||
$prefix = 'GD'; // 前缀
|
||||
$random = strtoupper(substr(md5(uniqid()), 0, 5)); // 5位随机字母数字
|
||||
|
||||
return $prefix . $date . '-' . $random; // 如 GD20240702-AB3X9Z
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace app\ticket\logic;
|
||||
|
||||
use app\ticket\model\Categorie;
|
||||
use support\Log;
|
||||
use support\exception\BusinessException;
|
||||
|
||||
class CategorieLogic
|
||||
{
|
||||
public function list($params)
|
||||
{
|
||||
$where = [];
|
||||
$size = $params['size'] ?? 10;
|
||||
$current = $params['current'] ?? 1;
|
||||
return Categorie::with('translation')->where($where)->paginate($size, ['*'], 'page', $current);
|
||||
}
|
||||
|
||||
public function getAll($params)
|
||||
{
|
||||
$where = [];
|
||||
$where[] = ['status', '=', 1];
|
||||
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 {
|
||||
return Categorie::create($data);
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('分类创建失败', [
|
||||
'data' => $data,
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
throw new BusinessException('分类创建失败,请稍后重试', 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function edit(array $data)
|
||||
{
|
||||
try {
|
||||
$categorie = Categorie::updateOrCreate(['id' => $data['id']], $data);
|
||||
return $categorie;
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('分类编辑失败', [
|
||||
'data' => $data,
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
throw new BusinessException('分类编辑失败,请稍后重试', 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function delete(int $id)
|
||||
{
|
||||
try {
|
||||
$categorie = Categorie::where(['id'=>$id])->delete();
|
||||
return $categorie;
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('分类删除失败', [
|
||||
'id' => $id,
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
throw new BusinessException('分类删除失败,请稍后重试', 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace app\ticket\logic;
|
||||
|
||||
use app\ticket\model\Conversation;
|
||||
use support\Log;
|
||||
use support\exception\BusinessException;
|
||||
|
||||
class ConversationLogic
|
||||
{
|
||||
public function list($params)
|
||||
{
|
||||
$where = [];
|
||||
if (!empty($params['ticket_id'])) {
|
||||
$where['ticket_id'] = $params['ticket_id'];
|
||||
}
|
||||
$size = $params['size'] ?? 10;
|
||||
$current = $params['current'] ?? 1;
|
||||
return Conversation::where($where)->paginate($size, ['*'], 'page', $current);
|
||||
}
|
||||
|
||||
public function add(array $data)
|
||||
{
|
||||
try {
|
||||
return Conversation::create($data);
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('会话创建失败', [
|
||||
'data' => $data,
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
throw new BusinessException('会话创建失败,请稍后重试', 500);
|
||||
}
|
||||
}
|
||||
public function edit(array $data)
|
||||
{
|
||||
try {
|
||||
$conversation = Conversation::updateOrCreate(['id' => $data['id']], $data);
|
||||
return $conversation;
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('会话编辑失败', [
|
||||
'data' => $data,
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace app\ticket\logic;
|
||||
|
||||
use app\common\model\UserTokenLog;
|
||||
use app\common\model\Systems;
|
||||
use app\common\model\User;
|
||||
use app\common\model\UserSn;
|
||||
use app\common\utils\Jwt;
|
||||
use app\ticket\model\Ticket;
|
||||
use support\Redis;
|
||||
use support\exception\BusinessException;
|
||||
use support\Log;
|
||||
|
||||
class TicketLogic
|
||||
{
|
||||
public function list($params)
|
||||
{
|
||||
$where = [];
|
||||
if(!empty($params['categorie_id'])){
|
||||
$where[] = ['categorie_id', '=', $params['categorie_id']];
|
||||
}
|
||||
if(!empty($params['user_id'])){
|
||||
$where[] = ['user_id', '=', $params['user_id']];
|
||||
}
|
||||
if(!empty($params['status'])){
|
||||
$where[] = ['status', '=', $params['status']];
|
||||
}
|
||||
$size = $params['size']??10;
|
||||
$current = $params['current']??1;
|
||||
|
||||
return Ticket::with('attachments')->with('categorie')->with('categorie.translation')->where($where)->orderBy('id','desc')->paginate($size, ['*'], 'page', $current);
|
||||
}
|
||||
public function add(array $data)
|
||||
{
|
||||
$data['status'] = 1;
|
||||
$data['code'] = self::generateSimpleTicketNo();
|
||||
try {
|
||||
return Ticket::create($data);
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('工单创建失败', [
|
||||
'data' => $data,
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
throw new BusinessException('工单创建失败,请稍后重试', 500);
|
||||
}
|
||||
}
|
||||
public function edit(array $data)
|
||||
{
|
||||
try {
|
||||
unset($data['code']);
|
||||
$ticket = Ticket::updateOrCreate(['id' => $data['id']],$data);
|
||||
return $ticket;
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('工单编辑失败', [
|
||||
'data' => $data,
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
throw new BusinessException('工单编辑失败,请稍后重试', 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function find(int $id)
|
||||
{
|
||||
$ticket = Ticket::find($id);
|
||||
return $ticket;
|
||||
}
|
||||
|
||||
public static function generateSimpleTicketNo(): string
|
||||
{
|
||||
$date = date('Ymd'); // 日期
|
||||
$prefix = 'GD'; // 前缀
|
||||
$random = strtoupper(substr(md5(uniqid()), 0, 5)); // 5位随机字母数字
|
||||
|
||||
return $prefix . $date . '-' . $random; // 如 GD20240702-AB3X9Z
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace app\ticket\model;
|
||||
|
||||
use app\common\model\Resource;
|
||||
use app\common\model\Role;
|
||||
use app\common\model\Systems;
|
||||
use support\Model;
|
||||
|
||||
/**
|
||||
* users 用户表
|
||||
* @property integer $id 用户ID(主键)
|
||||
* @property string $ticket_id 工单编号
|
||||
* @property string $user_id 分类id
|
||||
* @property string $original_name 内容
|
||||
* @property string $storage_path 排序
|
||||
* @property string $mime_type 状态
|
||||
* @property integer $file_size 创建人id
|
||||
* @property string $created_at
|
||||
* @property string $updated_at
|
||||
*/
|
||||
class Attachment extends Model
|
||||
{
|
||||
/**
|
||||
* The connection name for the model.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
protected $connection = 'mysql';
|
||||
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'tkt_ticket_attachment';
|
||||
|
||||
/**
|
||||
* 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 = [
|
||||
'ticket_id',
|
||||
'user_id',
|
||||
'original_name',
|
||||
'storage_path',
|
||||
'mime_type',
|
||||
'file_size'
|
||||
];
|
||||
|
||||
public function ticket(){
|
||||
return $this->belongsTo(Ticket::class, 'ticket_id', 'id');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace app\ticket\model;
|
||||
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use support\Model;
|
||||
|
||||
/**
|
||||
* ticket_categorie 工单分类表
|
||||
* @property integer $id 主键
|
||||
* @property string $name 分类名称
|
||||
* @property string $description 分类描述
|
||||
* @property string $created_at 创建时间
|
||||
* @property string $updated_at 更新时间
|
||||
* @property string $deleted_at 删除时间
|
||||
*/
|
||||
class Categorie extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
protected $connection = 'mysql';
|
||||
protected $table = 'tkt_ticket_categorie';
|
||||
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 = [
|
||||
'name',
|
||||
'description',
|
||||
];
|
||||
|
||||
/**
|
||||
* 单条翻译
|
||||
*/
|
||||
public function translation()
|
||||
{
|
||||
return $this->hasOne(CategorieTranslation::class, 'categorie_id')->where('locale', locale());
|
||||
}
|
||||
|
||||
/**
|
||||
* 多条翻译
|
||||
*/
|
||||
public function translations()
|
||||
{
|
||||
return $this->hasMany(CategorieTranslation::class, 'categorie_id');
|
||||
}
|
||||
|
||||
public function ticket(){
|
||||
return $this->hasOne(Ticket::class, 'categorie_id', 'id');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace app\ticket\model;
|
||||
|
||||
use support\Model;
|
||||
|
||||
/**
|
||||
* ticket_categorie_translation 工单分类多语言表
|
||||
* @property integer $id 主键
|
||||
* @property integer $categorie_id 分类ID
|
||||
* @property string $locale 语言
|
||||
* @property string $name 分类名称
|
||||
* @property string $description 分类描述
|
||||
* @property string $created_at 创建时间
|
||||
* @property string $updated_at 更新时间
|
||||
*/
|
||||
class CategorieTranslation extends Model
|
||||
{
|
||||
protected $connection = 'mysql';
|
||||
protected $table = 'tkt_ticket_categorie_translation';
|
||||
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 = [
|
||||
'categorie_id',
|
||||
'locale',
|
||||
'name',
|
||||
'description',
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace app\ticket\model;
|
||||
|
||||
use support\Model;
|
||||
|
||||
/**
|
||||
* ticket_conversation 工单会话表
|
||||
* @property integer $id 主键
|
||||
* @property integer $ticket_id 工单ID
|
||||
* @property integer $user_id 用户ID
|
||||
* @property string $content 会话内容
|
||||
* @property string $created_at 创建时间
|
||||
* @property string $updated_at 更新时间
|
||||
*/
|
||||
class Conversation extends Model
|
||||
{
|
||||
protected $connection = 'mysql';
|
||||
protected $table = 'tkt_ticket_conversation';
|
||||
protected $primaryKey = 'id';
|
||||
public $timestamps = true;
|
||||
protected $dateFormat = 'U';
|
||||
|
||||
protected $fillable = [
|
||||
'ticket_id',
|
||||
'user_id',
|
||||
'content',
|
||||
'attachment',
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
namespace app\ticket\model;
|
||||
|
||||
use app\common\model\Resource;
|
||||
use app\common\model\Role;
|
||||
use app\common\model\Systems;
|
||||
use support\Model;
|
||||
|
||||
/**
|
||||
* users 用户表
|
||||
* @property integer $id 用户ID(主键)
|
||||
* @property string $code 工单编号
|
||||
* @property string $categorie_id 分类id
|
||||
* @property string $content 内容
|
||||
* @property string $sort 排序
|
||||
* @property integer $status 状态
|
||||
* @property string $user_id 创建人id
|
||||
* @property string $created_at
|
||||
* @property string $updated_at
|
||||
*/
|
||||
class Ticket extends Model
|
||||
{
|
||||
/**
|
||||
* The connection name for the model.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
protected $connection = 'mysql';
|
||||
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'tkt_ticket';
|
||||
|
||||
/**
|
||||
* The primary key associated with the table.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $primaryKey = 'id';
|
||||
|
||||
/**
|
||||
* Indicates if the model should be timestamped.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = false;
|
||||
|
||||
protected $dateFormat = 'U';
|
||||
|
||||
/**
|
||||
* 在保存时手动设置时间戳
|
||||
*/
|
||||
protected static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
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',
|
||||
'categorie_id',
|
||||
'content',
|
||||
'sort',
|
||||
'status',
|
||||
'user_id'
|
||||
];
|
||||
|
||||
public function attachments(){
|
||||
return $this->hasMany(Attachment::class, 'ticket_id', 'id');
|
||||
}
|
||||
|
||||
public function categorie(){
|
||||
return $this->belongsTo(Categorie::class, 'categorie_id', 'id');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
namespace app\ticket\service;
|
||||
|
||||
use app\common\utils\translation\service\TranslationService;
|
||||
use app\queue\utils\Translat;
|
||||
use app\ticket\logic\CategorieLogic;
|
||||
use app\ticket\model\CategorieTranslation;
|
||||
use support\Db;
|
||||
use support\exception\BusinessException;
|
||||
|
||||
class CategorieService
|
||||
{
|
||||
public function list($params)
|
||||
{
|
||||
$result = (new CategorieLogic())->list($params);
|
||||
// $value=$result[0]->toArray();
|
||||
foreach ($result as $key => &$value) {
|
||||
$value['name'] = isset($value['translation']) ? $value['translation']['name'] : '';
|
||||
unset($value['translation']);
|
||||
}
|
||||
unset($value);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getAll($params)
|
||||
{
|
||||
$result = (new CategorieLogic())->getAll($params);
|
||||
foreach ($result as $key => &$value) {
|
||||
$value['name'] = isset($value['translation']) ? $value['translation']['name'] : '';
|
||||
unset($value['translation']);
|
||||
}
|
||||
unset($value);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public $translatFields = ['name'];
|
||||
|
||||
public function add(array $data)
|
||||
{
|
||||
try {
|
||||
Db::beginTransaction();
|
||||
$sourceLocale = locale();
|
||||
$traitsourceFields = Translat::extractSourceFields($data, $this->translatFields);
|
||||
|
||||
$result = (new CategorieLogic())->add($data);
|
||||
|
||||
(new TranslationService())->queueTranslations(
|
||||
'ticket_categorie',
|
||||
$result->id,
|
||||
$sourceLocale,
|
||||
$traitsourceFields
|
||||
);
|
||||
|
||||
Db::commit();
|
||||
return $result;
|
||||
} catch (\Throwable $e) {
|
||||
Db::rollback();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
public function edit(array $data)
|
||||
{
|
||||
try {
|
||||
Db::beginTransaction();
|
||||
$sourceLocale = locale();
|
||||
$traitsourceFields = Translat::extractSourceFields($data, $this->translatFields);
|
||||
|
||||
$result = (new CategorieLogic())->edit($data);
|
||||
|
||||
// (new TranslationService())->queueTranslations(
|
||||
// 'ticket_categorie',
|
||||
// $data['id'],
|
||||
// $sourceLocale,
|
||||
// $traitsourceFields
|
||||
// );
|
||||
CategorieTranslation::updateOrCreate(
|
||||
[
|
||||
'categorie_id' => $data['id'],
|
||||
'locale' => $sourceLocale,
|
||||
],
|
||||
$traitsourceFields
|
||||
);
|
||||
Db::commit();
|
||||
return $result;
|
||||
} catch (\Throwable $e) {
|
||||
Db::rollback();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
public function delete(int $id)
|
||||
{
|
||||
if(empty($id)){
|
||||
throw new BusinessException('id不能为空');
|
||||
}
|
||||
try {
|
||||
$result = (new CategorieLogic())->delete($id);
|
||||
return $result;
|
||||
} catch (\Throwable $e) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
<?php
|
||||
|
||||
namespace app\ticket\service;
|
||||
|
||||
use app\common\model\User;
|
||||
use app\common\service\MessageNotificationsService;
|
||||
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;
|
||||
|
||||
class ConversationService
|
||||
{
|
||||
public function list($params)
|
||||
{
|
||||
$locale = locale();
|
||||
// $locale = 'zh';
|
||||
$ticket_status = $locale == 'zh'? Constants::TICKET_STATUS_ZH:Constants::TICKET_STATUS_EN;
|
||||
// $ticket_status = Constants::TICKET_STATUS_ZH;
|
||||
// $params['locale'] = locale();
|
||||
$result = (new ConversationLogic())->list($params);
|
||||
|
||||
$status_fanyi = array_map(fn($v) => "{{{$v}}}", array_flip(Constants::TICKET_STATUS));
|
||||
$ossservice = new OssService();
|
||||
foreach ($result as $key => $value) {
|
||||
$value=$value->toArray();
|
||||
$value['content'] = str_replace($status_fanyi,$ticket_status,$value['content']);
|
||||
$value['attachment'] = empty($value['attachment'])?[]:unserialize($value['attachment']);
|
||||
foreach ($value['attachment'] as $k => $attachment) {
|
||||
$value['attachment'][$k]['storage_path_full'] = (!empty($attachment))?$ossservice->generatePrivateUrl($attachment['storage_path']):'';
|
||||
}
|
||||
$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;
|
||||
}
|
||||
|
||||
public function add(array $data)
|
||||
{
|
||||
try {
|
||||
$data['attachment'] = serialize($data['attachment']);
|
||||
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'] : '';
|
||||
|
||||
$userDefault = [1, 75, 78];
|
||||
$tiket_content = $ticket['content'];
|
||||
if (empty($conversation)) { //没有沟通记录
|
||||
$title = '新工单提醒-'.$categorieName;
|
||||
$notice_user_id = $userDefault;
|
||||
}else{
|
||||
$title = '工单回复';
|
||||
$tiket = (new TicketLogic())->find($conversation['ticket_id']);
|
||||
if($data['user_id'] != $tiket['user_id']){
|
||||
$notice_user_id = [$tiket['user_id']];
|
||||
}else{
|
||||
$conversationLast = Conversation::where('ticket_id', '=', $conversation['ticket_id'])
|
||||
->where('user_id', '!=', $data['user_id'])
|
||||
->orderBy('id', 'desc')
|
||||
->first();
|
||||
|
||||
$notice_user_id = (!empty($conversationLast['user_id']))? [$conversationLast['user_id']]:$userDefault;
|
||||
}
|
||||
$tiket_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']);
|
||||
|
||||
$reply = $content?($content."\n".'工单内容:'):'' ;
|
||||
}
|
||||
|
||||
$notice = ['sender_id' => 0, //发送人ID 0默认系统
|
||||
'sender_type' => 'system', //发送者类型 user admin system
|
||||
'title' => $title, //标题
|
||||
'content' => ($reply??'') . $tiket_content, //内容
|
||||
'scene' => 1, //场景 0系统公共 1系统通知
|
||||
'recipient' => $notice_user_id, //接收人 空为全部
|
||||
'push_method' => 0 //推送方式0系统推送1手动推送
|
||||
];
|
||||
|
||||
// 异步推送
|
||||
\Webman\RedisQueue\Redis::send('notice', $notice);
|
||||
|
||||
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 {
|
||||
Db::beginTransaction();
|
||||
$data['attachment'] = serialize($data['attachment']);
|
||||
$result = (new ConversationLogic())->edit($data);
|
||||
Db::commit();
|
||||
return $result;
|
||||
} catch (\Throwable $e) {
|
||||
Db::rollback();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
<?php
|
||||
|
||||
namespace app\ticket\service;
|
||||
|
||||
use app\common\model\User;
|
||||
use app\ticket\logic\AttachmentLogic;
|
||||
use app\ticket\logic\ConversationLogic;
|
||||
use app\ticket\logic\TicketLogic;
|
||||
use app\ticket\model\Ticket;
|
||||
use config\constants\Constants;
|
||||
use support\Db;
|
||||
use support\exception\BusinessException;
|
||||
use support\Log;
|
||||
|
||||
class TicketService
|
||||
{
|
||||
|
||||
public function list($params)
|
||||
{
|
||||
$res = (new TicketLogic())->list($params);
|
||||
foreach ($res as $k => &$v) {
|
||||
$name = isset($v['categorie']['translation']) ? $v['categorie']['translation']['name'] : '';
|
||||
if(isset($res[$k]['categorie'])){
|
||||
$res[$k]['categorie']['name'] = $name;
|
||||
}
|
||||
if (isset($v['categorie']['translation'])){
|
||||
unset($res[$k]['categorie']['translation']);
|
||||
}
|
||||
foreach ($v['attachments'] as &$attachments) {
|
||||
$attachments['storage_path_full'] = (new \app\common\service\OssService())->generatePrivateUrl($attachments['storage_path']);
|
||||
}
|
||||
|
||||
$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);
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
public function add(array $data)
|
||||
{
|
||||
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']);
|
||||
}
|
||||
|
||||
$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'],
|
||||
];
|
||||
(new ConversationService())->add($conversation);
|
||||
|
||||
return $result;
|
||||
} catch (\Throwable $e) {
|
||||
Db::rollback();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
public function edit(array $data)
|
||||
{
|
||||
try {
|
||||
Db::beginTransaction();
|
||||
$logic = new TicketLogic();
|
||||
$result = $logic->find($data['id']);
|
||||
|
||||
if(empty($result)){
|
||||
throw new BusinessException('工单不存在');
|
||||
}
|
||||
if($result['user_id'] != $data['user_id']){
|
||||
throw new BusinessException('只能编辑自己的工单');
|
||||
}
|
||||
if($result['status'] != 1){
|
||||
throw new BusinessException('只能修改待受理工单');
|
||||
}
|
||||
|
||||
$attachment = $data['attachment']??[];
|
||||
$result = $logic->edit($data);
|
||||
|
||||
if(!empty($attachment)){
|
||||
(new AttachmentLogic())->edit($attachment, $result->id, $data['user_id']);
|
||||
}
|
||||
Db::commit();
|
||||
return $result;
|
||||
} catch (\Throwable $e) {
|
||||
Db::rollback();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
public function status(array $data)
|
||||
{
|
||||
try {
|
||||
Db::beginTransaction();
|
||||
$msg = $data['msg']??[];
|
||||
$ticket = (new TicketLogic())->find($data['id']);
|
||||
if(empty($ticket)){
|
||||
throw new BusinessException('工单不存在');
|
||||
}
|
||||
if($data['status'] <= $ticket->status){
|
||||
throw new BusinessException(trans('status_not_modified'));
|
||||
}
|
||||
|
||||
// if(!in_array($ticket->status, [Constants::TICKET_STATUS['PENDING'], Constants::TICKET_STATUS['CONFIRM']])
|
||||
// && empty($msg)){
|
||||
// throw new BusinessException('提交失败');
|
||||
// }
|
||||
|
||||
$ticket->status = $data['status'];
|
||||
$result = $ticket->save();
|
||||
|
||||
if(!empty($msg)){
|
||||
$conversation = [
|
||||
'ticket_id' => $ticket->id,
|
||||
'user_id' => $data['user_id'],
|
||||
'content' => '状态更新为{{'.array_search($data['status'],Constants::TICKET_STATUS).'}}:'.$msg
|
||||
];
|
||||
$res = (new ConversationLogic())->add($conversation);
|
||||
}
|
||||
|
||||
Db::commit();
|
||||
return $result;
|
||||
} catch (\Throwable $e) {
|
||||
Db::rollback();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
public function getStatus(array $data)
|
||||
{
|
||||
$locale = locale();
|
||||
$ticket_status = $locale == 'zh'? Constants::TICKET_STATUS_ZH:Constants::TICKET_STATUS_EN;
|
||||
|
||||
$status = [];
|
||||
foreach ($ticket_status as $key => $value) {
|
||||
$status[] = ['value' => $key, 'text' => $value];
|
||||
}
|
||||
|
||||
if (empty($data['id'])) {
|
||||
return $status;
|
||||
}
|
||||
|
||||
$res = (new TicketLogic())->find($data['id']);
|
||||
if(!empty($res) && $res->user_id == $data['user_id']){
|
||||
$status = [
|
||||
['value' => Constants::TICKET_STATUS['PENDING'], 'text' => $ticket_status[Constants::TICKET_STATUS['PENDING']]],
|
||||
['value' => Constants::TICKET_STATUS['REJECTED'], 'text' => $ticket_status[Constants::TICKET_STATUS['REJECTED']]],
|
||||
];
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user