三类工单基础

This commit is contained in:
2025-03-19 17:07:27 +08:00
parent eeb2ea1b8b
commit cf2a2892b5
12 changed files with 398 additions and 36 deletions

View File

@ -3,6 +3,7 @@
namespace plugin\ticket\controller;
use plugin\ticket\model\TicketRepair;
use plugin\ticket\model\TicketType;
use think\admin\Controller;
use think\admin\helper\QueryHelper;
@ -23,6 +24,7 @@ class Repair extends Controller
public function index()
{
$this->title = '维修工单管理';
$this->type_list = TicketType::getList();
TicketRepair::mQuery()->layTable(function () {
}, static function (QueryHelper $query) {
$query->equal('status')->like('title');

View File

@ -41,7 +41,7 @@ class Ticket extends Controller
$query->like(['title|content|contact_name|ticket_address|contact_phone#keyword'])
->dateBetween(['create_at'])
->equal(['status', 'type_id']);
$query->append(['imgs_arr', 'source_type_name', 'type_name', 'last_reply'])->with('approval');
$query->append(['imgs_arr', 'source_type_name', 'type_name', 'last_reply'])->with(['views', 'repairs', 'verifys']);
});
}

View File

@ -2,6 +2,7 @@
namespace plugin\ticket\controller;
use plugin\ticket\model\TicketType;
use plugin\ticket\model\TicketVerify;
use think\admin\Controller;
use think\admin\helper\QueryHelper;
@ -23,6 +24,7 @@ class Verify extends Controller
public function index()
{
$this->title = '验收工单管理';
$this->type_list = TicketType::getList();
TicketVerify::mQuery()->layTable(function () {
}, static function (QueryHelper $query) {
$query->equal('status')->like('title');

View File

@ -2,6 +2,7 @@
namespace plugin\ticket\controller;
use plugin\ticket\model\TicketType;
use plugin\ticket\model\TicketView;
use think\admin\Controller;
use think\admin\helper\QueryHelper;
@ -23,8 +24,9 @@ class View extends Controller
public function index()
{
$this->title = '查看工单管理';
$this->type_list = TicketType::getList();
TicketView::mQuery()->layTable(function () {
}, static function (QueryHelper $query) {
}, function (QueryHelper $query) {
$query->equal('status')->like('title');
$query->timeBetween('create_at');
});

View File

@ -99,12 +99,12 @@ class TicketTicket extends Model
return $this->belongsTo(SystemUser::class, 'fz_user_id');
}
public function verify()
public function verifys()
{
return $this->hasMany(TicketVerify::class, 'ticket_id')->order('create_at', 'desc');
}
public function repair()
public function repairs()
{
return $this->hasMany(TicketRepair::class, 'ticket_id')->order('create_at', 'desc');
}
@ -113,6 +113,20 @@ class TicketTicket extends Model
return $this->hasMany(TicketView::class, 'ticket_id')->order('create_at', 'desc');
}
public function view_process() {
return $this->belongsTo(ApprovalInstance::class, 'view_pid', 'id');
}
public function repair_process()
{
return $this->belongsTo(ApprovalInstance::class, 'repair_pid', 'id');
}
public function verify_process()
{
return $this->belongsTo(ApprovalInstance::class, 'verify_pid', 'id');
}
public function repair_accept()
{
return $this->hasMany(TicketRepairAccept::class, 'ticket_id')->order('create_at', 'desc');

View File

@ -0,0 +1,72 @@
{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='repair/index_search'}
<table class="layui-hide" data-url="{$request->url()}" data-target-search="form.form-search" id="Table" lay-filter="Table"></table>
</div>
</div>
</div>
<script type="text/html" id="toolbar">
<!--{if auth("edit")}-->
<a data-modal="{:url('edit')}?id={{ d.id }}" data-height="80%" data-width="80%" class="layui-btn layui-btn-xs layui-btn-normal" title="修改">修改</a>
<!--{/if}-->
<!--{if auth("remove")}-->
<a data-confirm="确定要删除此维修工单吗?" data-action="{:url('remove')}" data-value="id#{{ d.id }}" data-csrf="{:systoken('remove')}" class="layui-btn layui-btn-xs layui-btn-danger" title="删除">删除</a>
<!--{/if}-->
</script>
{/block}
{block name='style'}
<style>
</style>
{/block}
{block name='script'}
<script>
$(function () {
$('#Table').layTable({
height: 'full-250',
toolbar: true,
sort: {field: 'create_at', type: 'desc'},
title: '维修工单列表',
cols: [[
{field: 'create_at', title: '创建时间', width: 160, sort: true},
{field:'type_name', title:'工单类型', width:120},
{field:'title', title:'工单标题', width:160},
{field:'content', title:'工单内容', minWidth:100},
{field:'ticket_address', title:'工单地址', width:200, templet:function(item){
if (item.ticket_address) {
return `${item.ticket_region} ${item.ticket_address}`;
} else {
return '未填写地址';
}
}},
{field: 'imgs', title: '工单图片', width: 100, templet:function(item){
if (item.imgs) {
return item.imgs.split("|").map((img) => {
return laytpl('<a target="_blank" data-tips-hover data-tips-image="{{d}}"><i class="layui-icon layui-icon-picture"></i></a>').render(img)
}).concat(' ')
} else {
return '';
}
}},
{field:'status', title:'工单状态', width:100, templet:function(item){
if (item.status == 0) {
return '<span class="layui-badge layui-bg-red">未维修</span>';
} else {
return '<span class="layui-badge layui-bg-green">已维修</span>';
}
}},
{fixed: 'right', title:'操作', toolbar: '#toolbar', width:200}
]],
page: true
})
})
</script>
{/block}

View File

@ -0,0 +1,42 @@
<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="keyword" value="{:input('get.keyword')}" 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 class="layui-select" name="type_id">
<option value=''>-- 全部 --</option>
{foreach $type_list as $type}
<option value='{$type.id}'>{$type.name}</option>
{/foreach}
</select>
</div>
</div>
<div class="layui-form-item layui-inline">
<label class="layui-form-label">创建时间</label>
<div class="layui-input-inline">
<input data-date-range name="create_at" value="{:input('get.create_at')}" 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 class="layui-select" name="status">
<option value=''>-- 全部 --</option>
<option value='0'>未维修</option>
<option value='1'>已维修</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

@ -26,25 +26,9 @@
<!--{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("move")}-->
<a data-modal="{:url('move')}?id={{ d.id }}" data-height="80%" data-width="80%" class="layui-btn layui-btn-xs" title="分配">分配</a>
<!--{/if}-->
{{# } }}
{{# if (d.status == -1) { }}
<!--{if auth("approve")}-->
{{# if (d.approval == null) { }}
<a data-modal="{:url('approve')}?id={{ d.id }}" data-height="90%" data-width="50%" class="layui-btn layui-btn-xs" title="审核">审核</a>
{{# } else if (d.approval.status == 0 && d.approval.current.approver_id == {$user_id}) { }}
<a data-modal="{:url('approve')}?id={{ d.id }}" data-height="90%" data-width="50%" class="layui-btn layui-btn-xs" title="去审核">去审核</a>
{{# } }}
{{# } }}
<!--{/if}-->
{{# if (d.approval == null || d.approval.status != 1) { }}
<!--{if auth("edit")}-->
<a data-modal="{:url('edit')}?id={{ d.id }}" data-height="80%" data-width="80%" class="layui-btn layui-btn-xs layui-btn-danger" title="修改工单">修改</a>
<!--{/if}-->
{{# } }}
</script>
{/block}
@ -65,7 +49,7 @@
{field:'create_at', title: '工单创建时间', width: 160, sort: true},
{field:'source_type_name', title:'工单来源', width:120},
{field:'type_name', title:'工单类型', width:160},
{field:'content', title:'工单内容', minWidth:100},
{field:'content', title:'工单内容', minWidth:120},
{field:'ticket_address', title:'工单地址', width:200, templet:function(item){
if (item.ticket_address) {
return `${item.ticket_region} ${item.ticket_address}`;
@ -82,23 +66,39 @@
return '';
}
}},
{field:'status', title:'状态', width:80, templet:function(item){
if (item.approval != null) {
if (item.approval.status != 1) {
return item.approval.status == 2 ? '<span style="color:red;">审核不通过</span>' : '<span style="color:gray;">审核中</span>';
}
}
if(item.status < 0){
return '<span style="color:red;">待审核</span>';
}else if(item.status == 0){
return '<span style="color:red;">待分配</span>';
}else if(item.status == 1){
return '<span style="color:green;">已处理</span>';
}else if(item.status == 2){
return '<span style="color:gray;">已关闭</span>';
{field: 'view', title:'核验情况', width: 100, minWidth:100, templet:function(item){
if (item.view_pid) {
// 已有核验流程
} 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>`;
}
}},
{field: 'repair', title:'维修情况', width: 100, minWidth:100, templet:function(item){
if (!item.views || item.views.length === 0) {
// 还没有核验流程
return `请先核验`
}
if (item.repair_pid) {
// 已有维修流程
} 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>`;
}
}},
{field: 'verify', title:'验收情况', width: 100, minWidth:100, templet:function(item){
if (!item.views || item.views.length === 0) {
// 还没有核验流程
return `请先核验`
}
if (!item.repairs || item.repairs.length === 0) {
// 还没有维修流程
return `请先维修`
}
if (item.verify_pid) {
// 已有验收流程
} 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>`;
}
}},
{fixed: 'right', title:'操作', toolbar: '#toolbar', width:200}
]],
page: true

View File

@ -0,0 +1,72 @@
{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='verify/index_search'}
<table class="layui-hide" data-url="{$request->url()}" data-target-search="form.form-search" id="Table" lay-filter="Table"></table>
</div>
</div>
</div>
<script type="text/html" id="toolbar">
<!--{if auth("edit")}-->
<a data-modal="{:url('edit')}?id={{ d.id }}" data-height="80%" data-width="80%" class="layui-btn layui-btn-xs layui-btn-normal" title="修改">修改</a>
<!--{/if}-->
<!--{if auth("remove")}-->
<a data-confirm="确定要删除此验收工单吗?" data-action="{:url('remove')}" data-value="id#{{ d.id }}" data-csrf="{:systoken('remove')}" class="layui-btn layui-btn-xs layui-btn-danger" title="删除">删除</a>
<!--{/if}-->
</script>
{/block}
{block name='style'}
<style>
</style>
{/block}
{block name='script'}
<script>
$(function () {
$('#Table').layTable({
height: 'full-250',
toolbar: true,
sort: {field: 'create_at', type: 'desc'},
title: '验收工单列表',
cols: [[
{field: 'create_at', title: '创建时间', width: 160, sort: true},
{field:'type_name', title:'工单类型', width:120},
{field:'title', title:'工单标题', width:160},
{field:'content', title:'工单内容', minWidth:100},
{field:'ticket_address', title:'工单地址', width:200, templet:function(item){
if (item.ticket_address) {
return `${item.ticket_region} ${item.ticket_address}`;
} else {
return '未填写地址';
}
}},
{field: 'imgs', title: '工单图片', width: 100, templet:function(item){
if (item.imgs) {
return item.imgs.split("|").map((img) => {
return laytpl('<a target="_blank" data-tips-hover data-tips-image="{{d}}"><i class="layui-icon layui-icon-picture"></i></a>').render(img)
}).concat(' ')
} else {
return '';
}
}},
{field:'status', title:'工单状态', width:100, templet:function(item){
if (item.status == 0) {
return '<span class="layui-badge layui-bg-red">未验收</span>';
} else {
return '<span class="layui-badge layui-bg-green">已验收</span>';
}
}},
{fixed: 'right', title:'操作', toolbar: '#toolbar', width:200}
]],
page: true
})
})
</script>
{/block}

View File

@ -0,0 +1,42 @@
<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="keyword" value="{:input('get.keyword')}" 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 class="layui-select" name="type_id">
<option value=''>-- 全部 --</option>
{foreach $type_list as $type}
<option value='{$type.id}'>{$type.name}</option>
{/foreach}
</select>
</div>
</div>
<div class="layui-form-item layui-inline">
<label class="layui-form-label">创建时间</label>
<div class="layui-input-inline">
<input data-date-range name="create_at" value="{:input('get.create_at')}" 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 class="layui-select" name="status">
<option value=''>-- 全部 --</option>
<option value='0'>未验收</option>
<option value='1'>已验收</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

@ -0,0 +1,72 @@
{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='view/index_search'}
<table class="layui-hide" data-url="{$request->url()}" data-target-search="form.form-search" id="Table" lay-filter="Table"></table>
</div>
</div>
</div>
<script type="text/html" id="toolbar">
<!--{if auth("edit")}-->
<a data-modal="{:url('edit')}?id={{ d.id }}" data-height="80%" data-width="80%" class="layui-btn layui-btn-xs layui-btn-normal" title="修改">修改</a>
<!--{/if}-->
<!--{if auth("remove")}-->
<a data-confirm="确定要删除此核实工单吗?" data-action="{:url('remove')}" data-value="id#{{ d.id }}" data-csrf="{:systoken('remove')}" class="layui-btn layui-btn-xs layui-btn-danger" title="删除">删除</a>
<!--{/if}-->
</script>
{/block}
{block name='style'}
<style>
</style>
{/block}
{block name='script'}
<script>
$(function () {
$('#Table').layTable({
height: 'full-250',
toolbar: true,
sort: {field: 'create_at', type: 'desc'},
title: '核实工单列表',
cols: [[
{field: 'create_at', title: '创建时间', width: 160, sort: true},
{field:'type_name', title:'工单类型', width:120},
{field:'title', title:'工单标题', width:160},
{field:'content', title:'工单内容', minWidth:100},
{field:'ticket_address', title:'工单地址', width:200, templet:function(item){
if (item.ticket_address) {
return `${item.ticket_region} ${item.ticket_address}`;
} else {
return '未填写地址';
}
}},
{field: 'imgs', title: '工单图片', width: 100, templet:function(item){
if (item.imgs) {
return item.imgs.split("|").map((img) => {
return laytpl('<a target="_blank" data-tips-hover data-tips-image="{{d}}"><i class="layui-icon layui-icon-picture"></i></a>').render(img)
}).concat(' ')
} else {
return '';
}
}},
{field:'status', title:'工单状态', width:100, templet:function(item){
if (item.status == 0) {
return '<span class="layui-badge layui-bg-red">未核实</span>';
} else {
return '<span class="layui-badge layui-bg-green">已核实</span>';
}
}},
{fixed: 'right', title:'操作', toolbar: '#toolbar', width:200}
]],
page: true
})
})
</script>
{/block}

View File

@ -0,0 +1,42 @@
<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="keyword" value="{:input('get.keyword')}" 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 class="layui-select" name="type_id">
<option value=''>-- 全部 --</option>
{foreach $type_list as $type}
<option value='{$type.id}'>{$type.name}</option>
{/foreach}
</select>
</div>
</div>
<div class="layui-form-item layui-inline">
<label class="layui-form-label">创建时间</label>
<div class="layui-input-inline">
<input data-date-range name="create_at" value="{:input('get.create_at')}" 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 class="layui-select" name="status">
<option value=''>-- 全部 --</option>
<option value='0'>未核实</option>
<option value='1'>已核实</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>