Tickets.php 8.3 KB
<?php

namespace App\Models\WorkOrder;

use App\Models\Base;
use App\Models\Manage\ManageHr;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Support\Facades\Log;

class Tickets extends Base
{
    use HasFactory;

    protected $table = 'gl_tickets';

    const STATUS_PEDDING = 0; // 待处理
    const STATUS_PROCESSING = 1; // 处理中
    const STATUS_YANSHOU = 2; // 验收中
    const STATUS_COMPLETED = 3; // 已完成
    const STATUS_CLOSED = 9; // 已关闭,已失效,审核不通过,结束工单设置大一点,方便中途又要加状态

    /**
     * @return void
     * 关联的工单日志
     */
    public function logs()
    {
        return $this->hasMany(TicketLog::class, 'ticket_id', 'id');
    }

    /**
     * 关联项目
     */
    public function project()
    {
        return $this->belongsTo(TicketProject::class, 'project_id', 'id');
    }

    /**
     * 当前工单,保存参与的人员到 gl_ticket_logs 表
     * 逻辑说明:
     * 1. 如果当前项目是超迹,要把徐莹和第一负责人加进去,为参与人
     * 2. 若是域途项目,把黄小玉和第一负责人加进去,为参与人
     * 3. 若是V5V6的项目,则把组长和第一负责人加进去,为参与人
     */
    public function saveEngineers($engineer_ids = [])
    {
        $canyu = [
            $this->project->engineer_id, // 第一负责人
        ];

        if ($this->project->project_cate == 3)
            $canyu[] = 20; // 徐莹
         elseif ($this->project->project_cate == 4)
             $canyu[] = 85; // 黄小玉
        else{
            // todo V5V6 的项目, 组长能够给看到组员的工单
            $leaders = [];
            foreach (array_merge($engineer_ids, $canyu) as $engineer_id)
            {
                $engineer = ManageHr::where('manage_id', $engineer_id)->first();
                if ($engineer)
                {
                    $leader = ManageHr::where('is_leader', 1)
                        ->where('status', ManageHr::STATUS_ONE)
                        ->where('dept_id', $engineer->dept_id)
                        ->where('belong_group', $engineer->belong_group)
                        ->value('manage_id');
                    if ($leader)
                        $leaders[] = $leader;
                }

            }
            // 合并组长 id 到 $canyu
            $canyu = array_merge($canyu, $leaders);
        }

        $all_engineer_ids = array_unique(array_merge($canyu, $engineer_ids));

        foreach ($all_engineer_ids as $engineer_id)
        {
            try {
                $log = $this->logs()->where('engineer_id', $engineer_id)->first();
                if ($log && $log->is_engineer != in_array($engineer_id, $engineer_ids))
                {
                    $log->is_engineer = in_array($engineer_id, $engineer_ids);
                    $log->plan_end_at = $this->plan_end_at; // 新增时写入 plan_end_at
                    $log->save();
                }else
                {
                    // 利用唯一索引去重
                    $log = new TicketLog();
                    $log->engineer_id = $engineer_id;
                    $log->is_engineer = in_array($engineer_id, $engineer_ids);
                    $log->plan_end_at = $this->plan_end_at; // 新增时写入 plan_end_at
                    $this->logs()->save($log);
                }
            }catch (\Exception $exception){
                Log::error(" | ERRPR | Ticket saveEngineers {$exception->getMessage()} \n {$exception->getTraceAsString()}");
            }
        }

        // 删除没有参与当前工单的人员(若之前已有)
        $this->logs()->whereNotIn('engineer_id', $all_engineer_ids)->delete();
    }

    /**
     * TODO 这个是一个补充功能
     * 那些情况需要推送钉钉内部通知?
     * 1. 客户提交了工单
     *  - 通知第一负责人 (gl_ticket_logs 表做了标记)
     * 2. 客户补充了工单
     *  - 通知最近的聊天技术(gl_ticket_chats 表做了标记)
     * 3. 技术完成了工单
     *  - 通知第一负责人 (暂无,所以这里做补充,如果以后要把上面的逻辑也加进来也可以,只是我为了偷懒,暂时只考虑完成工单请款)
     */
    public function pushDing($type = 'finish')
    {
        try {
            $ding = new TicketDing();
            $ding->msgKey = 'sampleLink';
            $ding->table_name = 'gl_tickets';
            $ding->table_id = $this->id;

            if ($type == 'finish')
            {
                // 所有技术完成了工单,通知第一负责人 和 工单的提交人
                $userIds = [$this->project->engineer_id];
                if ($this->submit_side == 1) {
                    // A 端提的,还要通知提交人
                    $userIds[] = $this->submit_user_id;
                    // 去重
                    $userIds = array_unique($userIds);
                }
                $ding->userIds = json_encode($userIds);
                $ding->msgParam = json_encode([
                    'text' => "工单(ID: {$this->id}),已经全部完成,请访问查看详情!",
                    'title' => 'AI协同工单 - ' . $this->project->title,
                    'picUrl' => 'https://hub.globalso.com/logocm.png',
                    'messageUrl' => 'https://oa.quanqiusou.cn/afterorder?project_id=' . $this->project->uuid,
                ], JSON_UNESCAPED_UNICODE);
                $ding->save();
            }
        }catch (\Exception $exception){
            Log::error(" | ERRPR | Ticket {$exception->getMessage()} \n {$exception->getTraceAsString()}");
        }
    }

    /**
     * @remark :
     * @name   :getorderTypeOptions
     * @author :lyh
     * @method :post
     * @time   :2025/11/24 14:43
     */
    public function getorderTypeOptions()
    {
        $data = [
            '1' => ['资料上传', '美工设计', '网站修改', '优化问题', '优化报告', '网站同步', '页面翻译', '其他问题','关键词相关','上线审核','研发工单(客户不可见)'],
            '2' => ['资料上传', '美工设计', '网站修改', '优化问题', '优化报告', '网站同步', '页面翻译', '其他问题','关键词相关','上线审核','GEO项目','研发工单(客户不可见)'],
            '3' => ['功能问题', '操作问题', '数据问题', '功能需求', '培训需求', '其他问题','研发工单(客户不可见)'],
            '4' => ['账号问题', '报告分析', '效果问题', '发帖问题', '视频问题', '美工设计', '其他问题','研发工单(客户不可见)']
        ];
        $dataSon = [
            '研发工单'=>[
                '1'=>['工单系统'=>'李宇航','页面及可视化'=>'刘俊杰','翻译'=>'李文涛','v5问题'=>'张关杰','其他问题'=>''],
                '2'=>['工单系统'=>'李宇航','oa管理系统'=>'李宇航','v6管理系统'=>'李宇航','社媒分享'=>'李宇航','C端页面生成'=>'李小龙','页面及可视化'=>'刘俊杰','翻译'=>'李文涛','其他问题'=>''],
                '3'=>['Whatsapp'=>'赵彬吉','邮件群发'=>'邓超','社媒'=>'何正兵','AI模型'=>'何正兵','其他问题'=>'朱世亮'],
                '4'=>['Whatsapp'=>'赵彬吉','邮件群发'=>'邓超','社媒'=>'何正兵','AI模型'=>'何正兵','其他问题'=>'朱世亮'],
            ]
        ];
        return ['type'=>$data, 'data'=>$dataSon];
    }

    /**
     * @remark :客户提交工单类型
     * @name   :getApiOrderTypeOptions
     * @author :lyh
     * @method :post
     * @time   :2025/11/27 17:01
     */
    public function getApiOrderTypeOptions()
    {
        $data = [
            '1' => ['资料上传', '美工设计', '网站修改', '优化问题', '优化报告', '网站同步', '页面翻译', '其他问题','关键词相关','上线审核'],
            '2' => ['资料上传', '美工设计', '网站修改', '优化问题', '优化报告', '网站同步', '页面翻译', '其他问题','关键词相关','上线审核','GEO项目'],
            '3' => ['功能问题', '操作问题', '数据问题', '功能需求', '培训需求', '其他问题'],
            '4' => ['账号问题', '报告分析', '效果问题', '发帖问题', '视频问题', '美工设计', '其他问题',]
        ];
        return ['type'=>$data];
    }
}