审核详情

This commit is contained in:
2025-03-20 10:08:23 +08:00
parent 05a0577d3e
commit 4046811b6d
9 changed files with 521 additions and 148 deletions

View File

@ -7,6 +7,9 @@ use think\admin\Controller;
use think\admin\helper\QueryHelper;
use think\admin\model\SystemUser;
/**
* 审核流程管理
*/
class Approval extends Controller
{
/**

View File

@ -0,0 +1,180 @@
<?php
namespace plugin\ticket\controller;
use plugin\ticket\model\ApprovalStep;
use plugin\ticket\model\TicketTicket;
use think\admin\Controller;
use plugin\ticket\model\ApprovalInstance as Model;
use think\admin\helper\QueryHelper;
use think\admin\model\SystemUser;
use think\exception\HttpResponseException;
/**
* 去审核
*/
class ApprovalInstance extends Controller
{
/**
* 审批流程列表
* @auth true
* @menu true
*/
public function index()
{
$this->title = '审批流程管理';
$this->user_id = $this->request->session('user')['id'];
Model::mQuery()->layTable(function () {
}, function (QueryHelper $query) {
$query->like('title')->equal('status');
$query->dateBetween('create_time');
$query->with(['steps'])->append(['current', 'status_text']);
});
}
/**
* 审批流程详情
* @return void
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function detail()
{
$this->title = '审批流程详情';
$this->user_id = $this->request->session('user')['id'];
$this->id = $this->request->get('id');
$instance = Model::query()->where('id', '=', $this->id)->with(['steps', 'process'])->append(['current'])->findOrEmpty();
if ($instance->isEmpty()) {
$this->error('审批流程不存在');
}
$this->vo = $instance;
$this->instance = $instance;
$this->steps = $instance->steps;
$this->step_index = $instance->current_step;
if (sizeof($instance->steps) <= ($instance->current_step + 1)) {
$this->next_step = ApprovalStep::mk(['approver_type' => 0]);
} else {
$this->next_step = $instance->steps[$instance->current_step + 1];
}
$this->users = SystemUser::query()->field('id,username,nickname')->select();
$this->process = $instance->process;
switch ($instance->process->type) {
case 'HSSH':
// 核实工单
$this->ticket = TicketTicket::query()->where('view_pid', '=', $instance->id)->with(['views', 'repairs', 'verifys'])->findOrEmpty();
break;
case 'WXSH':
// 维修审核
$this->ticket = TicketTicket::query()->where('repair_pid', '=', $instance->id)->with(['views', 'repairs', 'verifys'])->findOrEmpty();
break;
case 'YSSH':
// 验收审核
$this->ticket = TicketTicket::query()->where('verify_pid', '=', $instance->id)->with(['views', 'repairs', 'verifys'])->findOrEmpty();
break;
default:
$this->ticket = TicketTicket::mk([]);
}
$this->fetch();
}
/**
* 取消审批
* @auth true
* @return void
*/
public function cancel()
{
$this->id = $this->request->param('id');
$instance = Model::query()->where('id', '=', $this->id)->with(['steps'])->append(['current'])->findOrEmpty();
if ($instance->isEmpty()) {
$this->error('审批流程不存在');
}
if ($instance->status !== 0) {
$this->error('当前无法取消该审批流程');
} else {
Model::mk()->startTrans();
try {
foreach ($instance->steps as $step) {
if ($step->status === 0) {
$step->status = -1;
$step->save();
}
}
$instance->status = -1;
$instance->save();
} catch (\Exception $e) {
Model::mk()->rollback();
$this->error($e->getMessage());
}
$this->success('取消审批成功');
}
}
/**
* 进行审核
* @return void
* @throws \Exception
*
* @auth true
* @menu true
*/
public function do_approve()
{
$data = $this->_vali([
'id.require'=>'请指定当前审核ID!',
'step_index.require'=>'请指定当前步骤!',
'status.require'=>'请指定审核结果!',
'content.default'=>'',
]);
$adminInfo = $this->request->session('user');
$instance = Model::query()->with('steps')->findOrEmpty($data['id']);
if ($instance->isEmpty()) {
$this->error('审核流程不存在!');
}
if ($instance->status == 1) {
$this->error('工单已通过,请勿重复操作!');
} else if ($instance->status == 2) {
$this->error('工单已驳回,请勿重复操作!');
}
if ($instance->current_step != $data['step_index']) {
$this->error('当前步骤不正确!');
}
if ($instance->current->approver_id != $adminInfo['id']) {
$this->error('您不是当前审核人,请勿操作!');
}
Model::mk()->startTrans();
try {
$instance->current->status = $data['status'];
$instance->current->content = $data['content'];
$instance->current->approve_time = date('Y-m-d H:i:s');
$instance->current->save();
if ($data['status'] == 2) {
$instance->status = 2;
} else {
$instance->current_step++;
if ($instance->current_step >= count($instance->steps)) {
$instance->status = 1;
} else {
$step = $instance->steps[$instance->current_step];
if ($step['approver_type'] == 3) {
$approve_data = $this->_vali([
'approver_id.require' => '请指定审核人!',
]);
$step->approver_id = $approve_data['approver_id'];
$step->save();
}
}
}
$instance->save();
Model::mk()->commit();
} catch (HttpResponseException $e) {
Model::mk()->rollback();
throw $e;
} catch (\Exception $e) {
Model::mk()->rollback();
$this->error("审核失败");
}
$this->success('审核成功!');
}
}

View File

@ -496,79 +496,7 @@ class Ticket extends Controller
}
}
/**
* 进行审核
* @return void
* @throws \Exception
*
* @auth true
* @menu true
*/
public function do_approve()
{
$data = $this->_vali([
'id.require'=>'请指定工单ID!',
'instance_id.require'=>'请指定当前审核ID!',
'step_index.require'=>'请指定当前步骤!',
'status.require'=>'请指定审核结果!',
'content.default'=>'',
]);
$ticket = TicketTicket::query()->findOrEmpty($data['id']);
if ($ticket->isEmpty()) {
$this->error('工单不存在!');
}
$adminInfo = $this->request->session('user');
$instance = ApprovalInstance::query()->with('steps')->findOrEmpty($data['instance_id']);
if ($instance->isEmpty()) {
$this->error('审核流程不存在!');
}
if ($instance->status == 1) {
$this->error('工单已通过,请勿重复操作!');
} else if ($instance->status == 2) {
$this->error('工单已驳回,请勿重复操作!');
}
if ($instance->current_step != $data['step_index']) {
$this->error('当前步骤不正确!');
}
if ($instance->current->approver_id != $adminInfo['id']) {
$this->error('您不是当前审核人,请勿操作!');
}
ApprovalInstance::mk()->startTrans();
try {
$instance->current->status = $data['status'];
$instance->current->content = $data['content'];
$instance->current->save();
if ($data['status'] == 2) {
$instance->status = 2;
} else {
$instance->current_step++;
if ($instance->current_step >= count($instance->steps)) {
$instance->status = 1;
$ticket->status = 0;
$ticket->save();
} else {
$step = $instance->steps[$instance->current_step];
if ($step['approver_type'] == 3) {
$approve_data = $this->_vali([
'approver_id.require' => '请指定审核人!',
]);
$step->approver_id = $approve_data['approver_id'];
$step->save();
}
}
}
$instance->save();
ApprovalInstance::mk()->commit();
} catch (HttpResponseException $e) {
ApprovalInstance::mk()->rollback();
throw $e;
} catch (\Exception $e) {
ApprovalInstance::mk()->rollback();
// $this->error("审核失败");
throw $e;
}
$this->success('审核成功!');
}
public function my() {
$this->title = '待我审核';

View File

@ -42,11 +42,10 @@ class ApprovalInstance extends Model
public function getStatusTextAttr($value, $data)
{
$statusMap = [
0 => '待提交',
1 => '进行中',
2 => '已通过',
3 => '已驳回',
4 => '已取消'
-1 => '已取消',
0 => '进行中',
1 => '已通过',
2 => '已驳回',
];
return $statusMap[$data['status']] ?? '未知';
}

View File

@ -0,0 +1,207 @@
<div class="layui-tab layui-tab-brief">
<ul class="layui-tab-title">
<li class="layui-this">审核信息</li>
<li>工单信息</li>
</ul>
<div class="layui-tab-content">
<div class="layui-tab-item layui-show">
<div class="layui-collapse">
<div class="layui-colla-item">
<div class="layui-colla-title">审核流程</div>
<div class="layui-colla-content">
<div class="layui-timeline">
<div class="layui-timeline-item">
<i class="layui-icon layui-timeline-axis"></i>
<div class="layui-timeline-content layui-text">
<h3 class="layui-timeline-title">提交审核</h3>
</div>
</div>
{foreach $instance.steps as $index=>$step}
<div class="layui-timeline-item">
<i class="layui-icon layui-timeline-axis"></i>
<div class="layui-timeline-content layui-text">
<h3 class="layui-timeline-title">{$index+1}{if $instance.current_step == $index}(当前步骤){/if}</h3>
<p>
{$step.title}
</p>
{if $step.status == 1}
<div class="layui-timeline-title">
<div class="layui-timeline-title">
<span class="layui-badge layui-bg-green">已通过</span>
{$step.approver.nickname}{$step.approve_time|date='Y-m-d H:i:s'}审核通过
</div>
</div>
{elseif $step.status == 2}
<div class="layui-timeline-title">
<div class="layui-timeline-title">
<span class="layui-badge layui-bg-red">已驳回</span>
{$step.approver.nickname}{$step.approve_time|date='Y-m-d H:i:s'}审核驳回
</div>
</div>
{else}
<div class="layui-timeline-title">
<span class="layui-badge layui-bg-blue">待审核</span>
</div>
{/if}
</div>
</div>
{/foreach}
</div>
</div>
</div>
</div>
<div class="layui-card">
<div class="layui-card-header">工单审核</div>
<div class="layui-card-body">
{if $instance.current && $instance.current.status == 0}
{if $instance.current.approver_id == $user_id}
<form class="layui-form" data-table-id="formDemo" action="{:url('do_approve')}" data-auto="true" method="post">
<input type="hidden" name="id" value="{$vo.id}">
<input type="hidden" name="instance_id" value="{$instance->id}">
<input type="hidden" name="step_index" value="{$instance.current_step}">
<div class="layui-form-item">
<label class="layui-form-label">审核结果</label>
<div class="layui-input-block">
<input type="radio" name="status" value="1" title="通过" checked>
<input type="radio" name="status" value="2" title="不通过">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">审核意见</label>
<div class="layui-input-block">
<textarea name="content" placeholder="请输入审核意见" class="layui-textarea"></textarea>
</div>
</div>
{if !($next_step->isEmpty()) && $next_step.approver_type == 3}
<div class="layui-form-item">
<label class="layui-form-label">请指定下一步审核人</label>
<div class="layui-input-block">
<select name="approver_id" lay-verify="required" lay-search>
<option value="">请选择审核人</option>
{foreach $users as $user}
<option value="{$user.id}">{$user.username}</option>
{/foreach}
</select>
</div>
</div>
{/if}
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn layui-btn-normal" type='submit'>立即提交</button>
<button class="layui-btn layui-btn-primary" type="reset">重置</button>
</div>
</div>
</form>
{else}
<div class="think-red">
<i class="layui-icon layui-icon-tips"></i>
当前工单正等待审核。
</div>
{/if}
{/if}
</div>
</div>
</div>
<div class="layui-tab-item">
<div class="layui-card">
<div class="layui-card-header">工单内容</div>
<div class="layui-card-body">
<div class="layui-table">
<table class="layui-table">
<tbody class="layui-table-body">
<tr>
<td style="width: 120px">工单编号</td>
<td>{$ticket.id|default=""}</td>
</tr>
<tr>
<td>工单标题</td>
<td>{$ticket.title|default=""}</td>
</tr>
<tr>
<td>工单类型</td>
<td>{$ticket.type_name|default=""}</td>
</tr>
<tr>
<td>工单地址</td>
<td>{$ticket.ticket_region|default=""} {$ticket.ticket_address|default=""}</td>
</tr>
<tr>
<td>工单内容</td>
<td>{$ticket.content|default=""}</td>
</tr>
<tr>
<td>反馈人信息</td>
<td>{$ticket.contact_name|default="未填写名称"} {$ticket.contact_phone|default="未填写联系方式"}</td>
</tr>
<tr>
<td>工单图片</td>
<td>
<div>
{if count($ticket.imgs_arr) > 0}
{foreach $ticket.imgs_arr as $img}
<img data-tips-image src="{$img}" alt="image" style="height: 100px;">
<span>&nbsp;</span>
{/foreach}
{else}
无图片
{/if}
</div>
</td>
</tr>
{if $ticket.lat && $ticket.lng}
<tr>
<td>位置</td>
<td>
<div id="map" style="height: 320px;"></div>
</td>
</tr>
{/if}
</tbody>
</table>
</div>
{if $ticket.lat && $ticket.lng}
<script src="https://map.qq.com/api/gljs?v=1.exp&key=T6XBZ-L33CB-TMFUL-JQ4D6-MKBTK-KNBED"></script>
<script>
function initMap() {
//定义地图中心点坐标
var center = new TMap.LatLng("{$ticket.lat}", "{$ticket.lng}")
//定义map变量,调用 TMap.Map() 构造函数创建地图
var map = new TMap.Map(document.getElementById('map'), {
center: center,//设置地图中心点坐标
zoom: 17.2, //设置地图缩放级别
pitch: 30, //设置俯仰角
});
var marker = new TMap.MultiMarker({
map: map,
styles: {
// 点标记样式
marker: new TMap.MarkerStyle({
width: 20, // 样式宽
height: 30, // 样式高
anchor: { x: 10, y: 30 }, // 描点位置
}),
},
geometries: [
// 点标记数据数组
{
// 标记位置(纬度,经度,高度)
position: center,
id: 'marker',
},
],
});
}
var mapInit = setInterval(function () {
if (window.TMap) {
clearInterval(mapInit)
initMap()
}
}, 500)
</script>
{/if}
</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,77 @@
{extend name="table"}
{block name="button"}
{/block}
{block name="content"}
<div class="layui-row">
<div class="layui-col">
<div class="article_list think-bg-white">
{include file='approval_instance/index_search'}
<table class="layui-hide" data-url="{$request->url()}" data-target-search="form.form-search" id="processTable" lay-filter="processTable"></table>
</div>
</div>
</div>
<script type="text/html" id="toolbar">
{{# if(d.status == 0) { }}
{{# if(d.create_id == {$user_id}) { }}
<!--{if auth("cancel")}-->
<a data-modal="{:url('cancel')}?id={{ d.id }}" data-width="50%" class="layui-btn layui-btn-xs">取消</a>
<!--{/if}-->
{{# } }}
{{# } }}
<!--{if auth("detail")}-->
<a data-modal="{:url('detail')}?id={{ d.id }}" data-height="90%" data-width="60%" class="layui-btn layui-btn-xs layui-btn-normal" title="详情">详情</a>
<!--{/if}-->
{{# if(d.status == 0) { }}
<!--{if auth("approve")}-->
{{# if(d.current.approver_id == {$user_id}) { }}
<a data-modal="{:url('detail')}?id={{ d.id }}" data-height="90%" data-width="50%" class="layui-btn layui-btn-xs" title="去审核">去审核</a>
{{# } }}
<!--{/if}-->
{{# } }}
</script>
{/block}
{block name='style'}
<style>
</style>
{/block}
{block name='script'}
<script>
$(function () {
$('#processTable').layTable({
height: 'full-250',
toolbar: true,
sort: {field: 'create_time', type: 'desc'},
title: '审核列表',
cols: [[
{field:'create_time', title: '创建时间', width: 160, sort: true},
{field:'title', title:'审核标题', width:160},
{field:'content', title:'审核说明', width:160},
{field:'status', title:'审核状态', width:100, templet:function(item){
if (item.status == 0) {
return '<span class="layui-badge layui-bg-red">未审核</span>';
} else if (item.status == 1) {
return '<span class="layui-badge layui-bg-green">已通过</span>';
} else {
return '<span class="layui-badge layui-bg-orange">已驳回</span>';
}
}},
{field:'create_name', title:'提请人', width:100},
{field:'current.approver.nickname', title:'下一步', width:100, templet:function(item){
if (item.current.approver) {
return item.current.approver.nickname;
} else {
return '';
}
}},
{align: 'center', toolbar: '#toolbar', title: '操作', width: 200}
]]
});
});
</script>
{/block}

View File

@ -0,0 +1,27 @@
<fieldset>
<legend>条件搜索</legend>
<form class="layui-form layui-form-pane form-search" action="{:request()->url()}" onsubmit="return false" method="get" autocomplete="off">
<div class="layui-form-item layui-inline">
<label class="layui-form-label">审核标题</label>
<div class="layui-input-inline">
<input name="title" value="{:input('get.title')}" placeholder="请输入审核标题" class="layui-input">
</div>
</div>
<div class="layui-form-item layui-inline">
<label class="layui-form-label">审核状态</label>
<div class="layui-input-inline">
<select name="status">
<option value="">请选择审核状态</option>
<option value="0" {if input('get.status', -1) == 0}selected{/if}>未审核</option>
<option value="1" {if input('get.status') == 1}selected{/if}>已通过</option>
<option value="2" {if input('get.status') == 2}selected{/if}>已驳回</option>
</select>
</div>
</div>
<div class="layui-form-item layui-inline">
<button class="layui-btn layui-btn-primary" lay-submit lay-filter="searchData"><i class="layui-icon">&#xe615;</i> 搜 索</button>
</div>
</form>
</fieldset>

View File

@ -1,7 +1,6 @@
<div class="layui-tab layui-tab-brief">
<ul class="layui-tab-title">
<li class="layui-this">基本信息</li>
<li>审核情况</li>
<li>现场核实情况</li>
<li>关联随手拍</li>
</ul>
@ -106,73 +105,6 @@
</div>
</div>
</div>
<div class="layui-tab-item">
<div class="layui-card">
<div class="layui-card-header">审核情况</div>
<div class="layui-card-body">
{empty name='instance'}
<div class="layui-card-body">
<div class="layui-alert layui-alert-danger">
<i class="layui-icon">&#xe69c;</i>
该工单没有提交审核流程
</div>
</div>
{else}
<div class="layui-timeline">
<div class="layui-timeline-item">
<i class="layui-icon layui-timeline-axis"></i>
<div class="layui-timeline-content layui-text">
<h3 class="layui-timeline-title">提交审核{if $step_index == -1}(当前步骤){/if}</h3>
</div>
</div>
{foreach $instance.steps as $index=>$step}
<div class="layui-timeline-item">
<i class="layui-icon layui-timeline-axis"></i>
<div class="layui-timeline-content layui-text">
<h3 class="layui-timeline-title">{$index+1}{if $step_index == $index}(当前步骤){/if}</h3>
<p>
{$step.title}
</p>
{if $step_index >= $index}
{if $step.status == 2}
<div class="layui-alert layui-alert-danger">
<i class="layui-icon">&#xe69c;</i>
审核未通过
</div>
{elseif $step.status == 1}
<div class="layui-alert layui-alert-success">
<i class="layui-icon">&#xe6af;</i>
审核通过
</div>
{elseif $step.status == 0}
<div class="layui-alert layui-alert-warning">
<i class="layui-icon">&#xe6b2;</i>
审核中
</div>
{/if}
<div class="layui-form-item">
<label class="layui-form-label">审核人</label>
<div class="layui-input-block">
{$step.approver.nickname|default=""}
</div>
</div>
{if $step.status != 0}
<div class="layui-form-item">
<label class="layui-form-label">审核意见</label>
<div class="layui-input-block">
{$step.content|default=""}
</div>
</div>
{/if}
{/if}
</div>
</div>
{/foreach}
</div>
{/empty}
</div>
</div>
</div>
<div class="layui-tab-item">
<div class="layui-card">
<div class="layui-card-header">现场核实情况</div>

View File

@ -72,9 +72,11 @@
if (item.view_process.status === 0) {
return `正在审核`
} else if (item.view_process.status === 1) {
return `已通过`
return `<a data-modal="{:url('view_ticket_create')}?ticket_id=${item.id}" data-height="80%" data-width="80%" class="layui-btn layui-btn-xs layui-btn-danger" title="创建核验工单">创建核验工单</a>`;
} else if (item.view_process.status === 2) {
return `<a data-modal="{:url('view_process_create')}?ticket_id=${item.id}" data-height="80%" data-width="80%" class="layui-btn layui-btn-xs layui-btn-danger" title="提请核验">提请核验</a>`;
return `<a data-modal="{:url('view_process_create')}?ticket_id=${item.id}" data-height="80%" data-width="80%" class="layui-btn layui-btn-xs layui-btn-normal" title="提请核验">已驳回</a>`;
} else if (item.view_process.status === -1) {
return `已取消`
}
} else {
return `<a data-modal="{:url('view_process_create')}?ticket_id=${item.id}" data-height="80%" data-width="80%" class="layui-btn layui-btn-xs layui-btn-normal" title="提请核验">提请核验</a>`;
@ -93,6 +95,15 @@
}
if (item.repair_pid) {
// 已有维修流程
if (item.repair_process.status === 0) {
return `正在审核`
} else if (item.repair_process.status === 1) {
return `已通过`
} else if (item.repair_process.status === 2) {
return `<a data-modal="{:url('repair_process_create')}?ticket_id=${item.id}" data-height="80%" data-width="80%" class="layui-btn layui-btn-xs layui-btn-danger" title="提请维修">提请维修</a>`;
} else if (item.repair_process.status === -1) {
return `已取消`
}
} else {
return `<a data-modal="{:url('repair_process_create')}?ticket_id=${item.id}" data-height="80%" data-width="80%" class="layui-btn layui-btn-xs layui-btn-normal" title="提请维修">提请维修</a>`;
}
@ -114,6 +125,15 @@
}
if (item.verify_pid) {
// 已有验收流程
if (item.verify_process.status === 0) {
return `正在审核`
} else if (item.verify_process.status === 1) {
return `已通过`
} else if (item.verify_process.status === 2) {
return `<a data-modal="{:url('verify_process_create')}?ticket_id=${item.id}" data-height="80%" data-width="80%" class="layui-btn layui-btn-xs layui-btn-danger" title="提请验收">提请验收</a>`;
} else if (item.verify_process.status === -1) {
return `已取消`
}
} else {
return `<a data-modal="{:url('verify_process_create')}?ticket_id=${item.id}" data-height="80%" data-width="80%" class="layui-btn layui-btn-xs layui-btn-normal" title="提请验收">提请验收</a>`;
}