You've already forked guangan
内外部工单
This commit is contained in:
@ -24,6 +24,8 @@ class Service extends Plugin
|
|||||||
['name' => '工单分类', 'icon' => 'layui-icon layui-icon-template-1', 'node' => "{$code}/type/index"],
|
['name' => '工单分类', 'icon' => 'layui-icon layui-icon-template-1', 'node' => "{$code}/type/index"],
|
||||||
['name' => '随手拍列表', 'icon' => 'layui-icon layui-icon-template-1', 'node' => "{$code}/user_share/index"],
|
['name' => '随手拍列表', 'icon' => 'layui-icon layui-icon-template-1', 'node' => "{$code}/user_share/index"],
|
||||||
['name' => '工单列表', 'icon' => 'layui-icon layui-icon-template-1', 'node' => "{$code}/ticket/index"],
|
['name' => '工单列表', 'icon' => 'layui-icon layui-icon-template-1', 'node' => "{$code}/ticket/index"],
|
||||||
|
['name' => '内部工单列表', 'icon' => 'layui-icon layui-icon-template-1', 'node' => "{$code}/ticket_inter/index"],
|
||||||
|
['name' => '外部工单列表', 'icon' => 'layui-icon layui-icon-template-1', 'node' => "{$code}/ticket_outer/index"],
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
@ -33,7 +33,7 @@ class Ticket extends Controller
|
|||||||
$query->like(['title|content|contact_name|ticket_address|contact_phone#keyword'])
|
$query->like(['title|content|contact_name|ticket_address|contact_phone#keyword'])
|
||||||
->dateBetween(['create_at'])
|
->dateBetween(['create_at'])
|
||||||
->equal(['status', 'type_id']);
|
->equal(['status', 'type_id']);
|
||||||
$query->append(['imgs_arr', 'status_text', 'type_name', 'last_reply']);
|
$query->append(['imgs_arr', 'source_type_name', 'status_text', 'type_name', 'last_reply']);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
77
plugs/think-plugs-ticket/src/controller/TicketInter.php
Normal file
77
plugs/think-plugs-ticket/src/controller/TicketInter.php
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace plugin\ticket\controller;
|
||||||
|
|
||||||
|
use plugin\ticket\model\TicketTicketInter;
|
||||||
|
use plugin\ticket\model\TicketType;
|
||||||
|
use think\admin\Controller;
|
||||||
|
use think\admin\helper\QueryHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内部工单管理
|
||||||
|
*/
|
||||||
|
class TicketInter extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 工单列表
|
||||||
|
* @auth true
|
||||||
|
* @menu true
|
||||||
|
* @return void
|
||||||
|
* @throws \think\db\exception\DataNotFoundException
|
||||||
|
* @throws \think\db\exception\DbException
|
||||||
|
* @throws \think\db\exception\ModelNotFoundException
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$this->title = '工单中心';
|
||||||
|
$this->type_list = TicketType::getList();
|
||||||
|
$this->user_id = $this->request->session('user')['id'];
|
||||||
|
TicketTicketInter::mQuery()->layTable(function () {
|
||||||
|
|
||||||
|
}, function (QueryHelper $query) {
|
||||||
|
$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', 'status_text', 'type_name', 'last_reply']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加工单
|
||||||
|
* @auth true
|
||||||
|
* @menu true
|
||||||
|
* @return void
|
||||||
|
* @throws \think\db\exception\DataNotFoundException
|
||||||
|
* @throws \think\db\exception\DbException
|
||||||
|
* @throws \think\db\exception\ModelNotFoundException
|
||||||
|
*/
|
||||||
|
public function add()
|
||||||
|
{
|
||||||
|
$this->title = '添加工单';
|
||||||
|
$this->types = TicketType::mk()->scope('active')->select();
|
||||||
|
TicketTicketInter::mForm('form');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function _form_filter(&$data)
|
||||||
|
{
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
$data['user_id'] = 0;
|
||||||
|
}
|
||||||
|
$data['status'] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查看工单
|
||||||
|
* @auth true
|
||||||
|
* @menu true
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function detail()
|
||||||
|
{
|
||||||
|
$this->title = '工单详情';
|
||||||
|
['id' => $id] = $this->_vali(['id.require' => '请指定工单ID!']);
|
||||||
|
$this->vo = TicketTicketInter::mk()->with(['user', 'type', 'reply'])->append(['imgs_arr', 'status_text', 'type_name', 'last_reply'])->find($id);
|
||||||
|
$this->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
77
plugs/think-plugs-ticket/src/controller/TicketOuter.php
Normal file
77
plugs/think-plugs-ticket/src/controller/TicketOuter.php
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace plugin\ticket\controller;
|
||||||
|
|
||||||
|
use plugin\ticket\model\TicketReply;
|
||||||
|
use plugin\ticket\model\TicketTicketOuter;
|
||||||
|
use plugin\ticket\model\TicketType;
|
||||||
|
use think\admin\Controller;
|
||||||
|
use think\admin\helper\QueryHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 外部工单管理
|
||||||
|
*/
|
||||||
|
class TicketOuter extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 工单列表
|
||||||
|
* @auth true
|
||||||
|
* @menu true
|
||||||
|
* @return void
|
||||||
|
* @throws \think\db\exception\DataNotFoundException
|
||||||
|
* @throws \think\db\exception\DbException
|
||||||
|
* @throws \think\db\exception\ModelNotFoundException
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$this->title = '工单中心';
|
||||||
|
$this->type_list = TicketType::getList();
|
||||||
|
$this->user_id = $this->request->session('user')['id'];
|
||||||
|
TicketTicketOuter::mQuery()->layTable(function () {
|
||||||
|
|
||||||
|
}, function (QueryHelper $query) {
|
||||||
|
$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', 'status_text', 'type_name', 'last_reply']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加工单
|
||||||
|
* @auth true
|
||||||
|
* @menu true
|
||||||
|
* @return void
|
||||||
|
* @throws \think\db\exception\DataNotFoundException
|
||||||
|
* @throws \think\db\exception\DbException
|
||||||
|
* @throws \think\db\exception\ModelNotFoundException
|
||||||
|
*/
|
||||||
|
public function add()
|
||||||
|
{
|
||||||
|
$this->title = '添加工单';
|
||||||
|
$this->types = TicketType::mk()->scope('active')->select();
|
||||||
|
TicketTicketOuter::mForm('form');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function _form_filter(&$data)
|
||||||
|
{
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
$data['user_id'] = 0;
|
||||||
|
}
|
||||||
|
$data['status'] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查看工单
|
||||||
|
* @auth true
|
||||||
|
* @menu true
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function detail()
|
||||||
|
{
|
||||||
|
$this->title = '工单详情';
|
||||||
|
['id' => $id] = $this->_vali(['id.require' => '请指定工单ID!']);
|
||||||
|
$this->vo = TicketTicketOuter::mk()->with(['user', 'type', 'reply'])->append(['imgs_arr', 'status_text', 'type_name', 'last_reply'])->find($id);
|
||||||
|
$this->fetch();
|
||||||
|
}
|
||||||
|
}
|
@ -82,4 +82,24 @@ class TicketTicket extends Model
|
|||||||
{
|
{
|
||||||
return $query->where('status', '>=', '0');
|
return $query->where('status', '>=', '0');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function userShares()
|
||||||
|
{
|
||||||
|
return $this->hasMany(TicketUserShare::class, 'linked_ticket_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeUnConf($query)
|
||||||
|
{
|
||||||
|
return $query->where('state', '=', '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeInter($query)
|
||||||
|
{
|
||||||
|
return $query->where('state', '=', '1');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeOuter($query)
|
||||||
|
{
|
||||||
|
return $query->where('state', '=', '2');
|
||||||
|
}
|
||||||
}
|
}
|
90
plugs/think-plugs-ticket/src/model/TicketTicketInter.php
Normal file
90
plugs/think-plugs-ticket/src/model/TicketTicketInter.php
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace plugin\ticket\model;
|
||||||
|
|
||||||
|
class TicketTicketInter extends TicketTicket
|
||||||
|
{
|
||||||
|
protected $append = ['status_text', 'type_name'];
|
||||||
|
protected $globalScope = ['inter'];
|
||||||
|
protected $table = 'ticket_ticket';
|
||||||
|
public function type()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(TicketType::class, 'type_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function user()
|
||||||
|
{
|
||||||
|
return $this->morphTo('user');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function reply()
|
||||||
|
{
|
||||||
|
return $this->hasMany(TicketReply::class, 'ticket_id')->order("create_at", 'asc');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getImgsArrAttr($value, $data)
|
||||||
|
{
|
||||||
|
return str2arr($data['imgs'] ?: '', '|');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLastReplyAttr($value, $data)
|
||||||
|
{
|
||||||
|
return $this->reply()->order('create_at', 'desc')->find();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSourceTypeNameAttr($value, $data)
|
||||||
|
{
|
||||||
|
if (!empty($this->getSourceTypeList()[$data['source_type']])) {
|
||||||
|
return $this->getSourceTypeList()[$data['source_type']];
|
||||||
|
} else {
|
||||||
|
return '未知';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSourceTypeList()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
0 => '其他',
|
||||||
|
1 => '用户随手拍',
|
||||||
|
2 => '工单',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTypeNameAttr($value, $data)
|
||||||
|
{
|
||||||
|
$type = $this->type()->find();
|
||||||
|
if (!empty($type)) {
|
||||||
|
return $type['name'];
|
||||||
|
} else {
|
||||||
|
return '未知';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStatusTextAttr($value, $data)
|
||||||
|
{
|
||||||
|
if (!empty($this->getStatusList()[$data['status']])) {
|
||||||
|
return $this->getStatusList()[$data['status']];
|
||||||
|
} else {
|
||||||
|
return '未知';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getStatusList()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
-1 => '已关闭',
|
||||||
|
0 => '待处理',
|
||||||
|
1 => '已作处理',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeAvail($query)
|
||||||
|
{
|
||||||
|
return $query->where('status', '>=', '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function userShares()
|
||||||
|
{
|
||||||
|
return $this->hasMany(TicketUserShare::class, 'linked_ticket_id');
|
||||||
|
}
|
||||||
|
}
|
90
plugs/think-plugs-ticket/src/model/TicketTicketOuter.php
Normal file
90
plugs/think-plugs-ticket/src/model/TicketTicketOuter.php
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace plugin\ticket\model;
|
||||||
|
|
||||||
|
class TicketTicketOuter extends TicketTicket
|
||||||
|
{
|
||||||
|
protected $append = ['status_text', 'type_name'];
|
||||||
|
protected $globalScope = ['outer'];
|
||||||
|
protected $table = 'ticket_ticket';
|
||||||
|
public function type()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(TicketType::class, 'type_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function user()
|
||||||
|
{
|
||||||
|
return $this->morphTo('user');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function reply()
|
||||||
|
{
|
||||||
|
return $this->hasMany(TicketReply::class, 'ticket_id')->order("create_at", 'asc');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getImgsArrAttr($value, $data)
|
||||||
|
{
|
||||||
|
return str2arr($data['imgs'] ?: '', '|');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLastReplyAttr($value, $data)
|
||||||
|
{
|
||||||
|
return $this->reply()->order('create_at', 'desc')->find();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSourceTypeNameAttr($value, $data)
|
||||||
|
{
|
||||||
|
if (!empty($this->getSourceTypeList()[$data['source_type']])) {
|
||||||
|
return $this->getSourceTypeList()[$data['source_type']];
|
||||||
|
} else {
|
||||||
|
return '未知';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSourceTypeList()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
0 => '其他',
|
||||||
|
1 => '用户随手拍',
|
||||||
|
2 => '工单',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTypeNameAttr($value, $data)
|
||||||
|
{
|
||||||
|
$type = $this->type()->find();
|
||||||
|
if (!empty($type)) {
|
||||||
|
return $type['name'];
|
||||||
|
} else {
|
||||||
|
return '未知';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStatusTextAttr($value, $data)
|
||||||
|
{
|
||||||
|
if (!empty($this->getStatusList()[$data['status']])) {
|
||||||
|
return $this->getStatusList()[$data['status']];
|
||||||
|
} else {
|
||||||
|
return '未知';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getStatusList()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
-1 => '已关闭',
|
||||||
|
0 => '待处理',
|
||||||
|
1 => '已作处理',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeAvail($query)
|
||||||
|
{
|
||||||
|
return $query->where('status', '>=', '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function userShares()
|
||||||
|
{
|
||||||
|
return $this->hasMany(TicketUserShare::class, 'linked_ticket_id');
|
||||||
|
}
|
||||||
|
}
|
@ -22,18 +22,13 @@
|
|||||||
<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>
|
<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}-->
|
||||||
<!--{if auth("move")}-->
|
<!--{if auth("move")}-->
|
||||||
<a data-modal="{:url('move')}?ticket_id={{ d.id }}" data-height="80%" data-width="80%" class="layui-btn layui-btn-xs" title="流转">流转</a>
|
<a data-modal="{:url('move')}?ticket_id={{ d.id }}" data-height="80%" data-width="80%" class="layui-btn layui-btn-xs" title="流转">分配</a>
|
||||||
<!--{/if}-->
|
|
||||||
<!--{if auth("reply")}-->
|
|
||||||
{{# if (d.last_reply && d.last_reply.user_id == {$user_id} && d.last_reply.status == 0) { }}
|
|
||||||
<a data-modal="{:url('reply')}?id={{ d.last_reply.id }}&ticket_id={{ d.id }}" data-height="80%" data-width="80%" class="layui-btn layui-btn-xs" title="回复">回复</a>
|
|
||||||
{{# }; }}
|
|
||||||
<!--{/if}-->
|
<!--{/if}-->
|
||||||
<!--{if auth("edit")}-->
|
<!--{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>
|
<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}-->
|
<!--{/if}-->
|
||||||
<!--{if auth("remove")}-->
|
<!--{if auth("remove")}-->
|
||||||
<a data-confirm="原则上不允许主动删除用户工单,是否继续删除?" data-action="{:url('remove')}" data-value="id#{{ d.id }}" class="layui-btn layui-btn-xs layui-btn-danger" title="删除">删除</a>
|
<a data-confirm="是否删除此工单?" data-action="{:url('remove')}" data-value="id#{{ d.id }}" class="layui-btn layui-btn-xs layui-btn-danger" title="删除">删除</a>
|
||||||
<!--{/if}-->
|
<!--{/if}-->
|
||||||
</script>
|
</script>
|
||||||
{/block}
|
{/block}
|
||||||
@ -53,10 +48,16 @@
|
|||||||
title: '工单列表',
|
title: '工单列表',
|
||||||
cols: [[
|
cols: [[
|
||||||
{field:'create_at', title: '工单创建时间', width: 160, sort: true},
|
{field:'create_at', title: '工单创建时间', width: 160, sort: true},
|
||||||
{field:'title', title:'标题', width:160},
|
{field:'source_type_name', title:'工单来源', width:120},
|
||||||
{field:'type_name', title:'工单类型', width:120},
|
{field:'type_name', title:'工单类型', width:160},
|
||||||
{field:'content', title:'工单内容', minWidth:100},
|
{field:'content', title:'工单内容', minWidth:100},
|
||||||
{field:'ticket_address', title:'工单地址', width: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){
|
{field: 'imgs', title: '工单图片', width: 100, templet:function(item){
|
||||||
if (item.imgs) {
|
if (item.imgs) {
|
||||||
return item.imgs.split("|").map((img) => {
|
return item.imgs.split("|").map((img) => {
|
||||||
|
65
plugs/think-plugs-ticket/src/view/ticket_inter/detail.html
Normal file
65
plugs/think-plugs-ticket/src/view/ticket_inter/detail.html
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
<div class="layui-card">
|
||||||
|
<div class="layui-card-header">工单内容</div>
|
||||||
|
<div class="layui-card-body">
|
||||||
|
<div class="layui-row">
|
||||||
|
工单编号:{$vo.id|default=""}
|
||||||
|
</div>
|
||||||
|
<div class="layui-row">
|
||||||
|
工单标题:{$vo.title|default=""}
|
||||||
|
</div>
|
||||||
|
<div class="layui-row">
|
||||||
|
反馈人信息:{$vo.contact_name|default="未填写名称"},
|
||||||
|
联系方式:{$vo.contact_phone|default="未填写联系方式"},
|
||||||
|
联系地址:{$vo.contact_address|default="未填写地址"}
|
||||||
|
</div>
|
||||||
|
<div class="layui-row">
|
||||||
|
工单类型:{$vo.type_name|default=""}
|
||||||
|
</div>
|
||||||
|
<div class="layui-row">
|
||||||
|
工单地址:{$vo.ticket_address|default=""}
|
||||||
|
</div>
|
||||||
|
<div class="layui-row">
|
||||||
|
工单内容:{$vo.content|default=""}
|
||||||
|
</div>
|
||||||
|
<div class="layui-row">
|
||||||
|
工单图片:
|
||||||
|
<div>
|
||||||
|
{foreach $vo.imgs_arr as $img}
|
||||||
|
<img data-tips-image src="{$img}" alt="image" style="height: 100px;">
|
||||||
|
<span> </span>
|
||||||
|
{/foreach}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="layui-card">
|
||||||
|
<div class="layui-card-header">工单流转详情</div>
|
||||||
|
<div class="layui-card-body">
|
||||||
|
<table id="replyTable" class="layui-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th lay-data='{field: "username", width: "120px"}'>工单处理人</th>
|
||||||
|
<th lay-data='{field: "type_name", width: "120px"}'>处理类型</th>
|
||||||
|
<th lay-data='{field: "create_at", width: "180px"}'>工单处理时间</th>
|
||||||
|
<th lay-data='{field: "content", minWidth: "200px"}'>处理内容</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{notempty name='vo.reply'}
|
||||||
|
{foreach $vo.reply as $reply}
|
||||||
|
<tr>
|
||||||
|
<td>{$reply.username|default=""}</td>
|
||||||
|
<td>{$reply.type_name|default=""}</td>
|
||||||
|
<td>{$reply.create_at|default=""}</td>
|
||||||
|
<td>{$reply.content|default=""}</td>
|
||||||
|
</tr>
|
||||||
|
{/foreach}
|
||||||
|
{else}
|
||||||
|
<tr>
|
||||||
|
<td colspan="999" class="text-center">暂无工单流转记录</td>
|
||||||
|
</tr>
|
||||||
|
{/notempty}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
41
plugs/think-plugs-ticket/src/view/ticket_inter/form.html
Normal file
41
plugs/think-plugs-ticket/src/view/ticket_inter/form.html
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<form class="layui-form layui-card" action="{:sysuri()}" data-auto="true" method="post" autocomplete="off" data-table-id="ticketTable">
|
||||||
|
<div class="layui-row">
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<label class="layui-form-label">工单标题</label>
|
||||||
|
<div class="layui-input-block">
|
||||||
|
<input type="text" name="title" value='{$vo.title|default=""}' required placeholder="请输入工单标题" class="layui-input">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<label class="layui-form-label">工单分类</label>
|
||||||
|
<div class="layui-input-block">
|
||||||
|
<select class="layui-select" name="type_id" required>
|
||||||
|
{foreach $types as $type}
|
||||||
|
<option value='{$type.id}'>{$type.name}</option>
|
||||||
|
{/foreach}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<label class="layui-form-label">工单内容</label>
|
||||||
|
<div class="layui-input-block">
|
||||||
|
<textarea data-textarea class="layui-textarea" name='content' required>{$vo.content|default=""}</textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<label class="layui-form-label">工单图片</label>
|
||||||
|
<div class="layui-input-block">
|
||||||
|
<input type="hidden" value='{$vo.imgs|default=""}' name="imgs">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{notempty name='id'}<input class="layui-input layui-hide" type='hidden' value='{$id}' name='id'>{/notempty}
|
||||||
|
<div class="layui-form-item text-center">
|
||||||
|
<button class="layui-btn layui-btn-normal" type='submit'>保存数据</button>
|
||||||
|
<button class="layui-btn layui-btn-danger" type='button' data-confirm="确定要取消编辑吗?" data-close>取消编辑</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<script>
|
||||||
|
$('[name="imgs"]').uploadMultipleImage()
|
||||||
|
</script>
|
86
plugs/think-plugs-ticket/src/view/ticket_inter/index.html
Normal file
86
plugs/think-plugs-ticket/src/view/ticket_inter/index.html
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
{extend name="table"}
|
||||||
|
|
||||||
|
{block name="button"}
|
||||||
|
<!--{if auth("add")}-->
|
||||||
|
<button type="button" class="layui-btn layui-btn-sm layui-btn-disabled" data-modal='{:url("add")}' data-title="添加工单">添加工单</button>
|
||||||
|
<!--{/if}-->
|
||||||
|
{/block}
|
||||||
|
|
||||||
|
{block name="content"}
|
||||||
|
<div class="layui-tab">
|
||||||
|
<div class="layui-row">
|
||||||
|
<div class="layui-col">
|
||||||
|
<div class="article_list think-bg-white">
|
||||||
|
{include file='ticket_inter/index_search'}
|
||||||
|
<table class="layui-hide" data-url="{$request->url()}" data-target-search="form.form-search" id="ticketTable" lay-filter="ticketTable"></table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script type="text/html" id="toolbar">
|
||||||
|
<!--{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 auth("move")}-->
|
||||||
|
<a data-modal="{:url('move')}?ticket_id={{ d.id }}" data-height="80%" data-width="80%" class="layui-btn layui-btn-xs" title="流转">分配</a>
|
||||||
|
<!--{/if}-->
|
||||||
|
<!--{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}-->
|
||||||
|
<!--{if auth("remove")}-->
|
||||||
|
<a data-confirm="是否删除此工单?" data-action="{:url('remove')}" data-value="id#{{ d.id }}" 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 () {
|
||||||
|
$('#ticketTable').layTable({
|
||||||
|
height: 'full-250',
|
||||||
|
toolbar: true,
|
||||||
|
sort: {field: 'create_at', type: 'desc'},
|
||||||
|
title: '工单列表',
|
||||||
|
cols: [[
|
||||||
|
{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:'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:80, templet:function(item){
|
||||||
|
if(item.status == 0){
|
||||||
|
return '<span style="color:red;">正在处理</span>';
|
||||||
|
}else if(item.status == 1){
|
||||||
|
return '<span style="color:green;">已处理</span>';
|
||||||
|
}else{
|
||||||
|
return '<span style="color:gray;">已关闭</span>';
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
|
||||||
|
{fixed: 'right', title:'操作', toolbar: '#toolbar', width:200}
|
||||||
|
]],
|
||||||
|
page: true
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
{/block}
|
@ -0,0 +1,49 @@
|
|||||||
|
<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">
|
||||||
|
<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">
|
||||||
|
<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">
|
||||||
|
<input data-date-range name="last_activity_at" value="{:input('get.last_activity_at')}" placeholder="请选择最后操作时间" class="layui-input">
|
||||||
|
</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"></i> 搜 索</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</fieldset>
|
65
plugs/think-plugs-ticket/src/view/ticket_outer/detail.html
Normal file
65
plugs/think-plugs-ticket/src/view/ticket_outer/detail.html
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
<div class="layui-card">
|
||||||
|
<div class="layui-card-header">工单内容</div>
|
||||||
|
<div class="layui-card-body">
|
||||||
|
<div class="layui-row">
|
||||||
|
工单编号:{$vo.id|default=""}
|
||||||
|
</div>
|
||||||
|
<div class="layui-row">
|
||||||
|
工单标题:{$vo.title|default=""}
|
||||||
|
</div>
|
||||||
|
<div class="layui-row">
|
||||||
|
反馈人信息:{$vo.contact_name|default="未填写名称"},
|
||||||
|
联系方式:{$vo.contact_phone|default="未填写联系方式"},
|
||||||
|
联系地址:{$vo.contact_address|default="未填写地址"}
|
||||||
|
</div>
|
||||||
|
<div class="layui-row">
|
||||||
|
工单类型:{$vo.type_name|default=""}
|
||||||
|
</div>
|
||||||
|
<div class="layui-row">
|
||||||
|
工单地址:{$vo.ticket_address|default=""}
|
||||||
|
</div>
|
||||||
|
<div class="layui-row">
|
||||||
|
工单内容:{$vo.content|default=""}
|
||||||
|
</div>
|
||||||
|
<div class="layui-row">
|
||||||
|
工单图片:
|
||||||
|
<div>
|
||||||
|
{foreach $vo.imgs_arr as $img}
|
||||||
|
<img data-tips-image src="{$img}" alt="image" style="height: 100px;">
|
||||||
|
<span> </span>
|
||||||
|
{/foreach}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="layui-card">
|
||||||
|
<div class="layui-card-header">工单流转详情</div>
|
||||||
|
<div class="layui-card-body">
|
||||||
|
<table id="replyTable" class="layui-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th lay-data='{field: "username", width: "120px"}'>工单处理人</th>
|
||||||
|
<th lay-data='{field: "type_name", width: "120px"}'>处理类型</th>
|
||||||
|
<th lay-data='{field: "create_at", width: "180px"}'>工单处理时间</th>
|
||||||
|
<th lay-data='{field: "content", minWidth: "200px"}'>处理内容</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{notempty name='vo.reply'}
|
||||||
|
{foreach $vo.reply as $reply}
|
||||||
|
<tr>
|
||||||
|
<td>{$reply.username|default=""}</td>
|
||||||
|
<td>{$reply.type_name|default=""}</td>
|
||||||
|
<td>{$reply.create_at|default=""}</td>
|
||||||
|
<td>{$reply.content|default=""}</td>
|
||||||
|
</tr>
|
||||||
|
{/foreach}
|
||||||
|
{else}
|
||||||
|
<tr>
|
||||||
|
<td colspan="999" class="text-center">暂无工单流转记录</td>
|
||||||
|
</tr>
|
||||||
|
{/notempty}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
41
plugs/think-plugs-ticket/src/view/ticket_outer/form.html
Normal file
41
plugs/think-plugs-ticket/src/view/ticket_outer/form.html
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<form class="layui-form layui-card" action="{:sysuri()}" data-auto="true" method="post" autocomplete="off" data-table-id="ticketTable">
|
||||||
|
<div class="layui-row">
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<label class="layui-form-label">工单标题</label>
|
||||||
|
<div class="layui-input-block">
|
||||||
|
<input type="text" name="title" value='{$vo.title|default=""}' required placeholder="请输入工单标题" class="layui-input">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<label class="layui-form-label">工单分类</label>
|
||||||
|
<div class="layui-input-block">
|
||||||
|
<select class="layui-select" name="type_id" required>
|
||||||
|
{foreach $types as $type}
|
||||||
|
<option value='{$type.id}'>{$type.name}</option>
|
||||||
|
{/foreach}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<label class="layui-form-label">工单内容</label>
|
||||||
|
<div class="layui-input-block">
|
||||||
|
<textarea data-textarea class="layui-textarea" name='content' required>{$vo.content|default=""}</textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<label class="layui-form-label">工单图片</label>
|
||||||
|
<div class="layui-input-block">
|
||||||
|
<input type="hidden" value='{$vo.imgs|default=""}' name="imgs">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{notempty name='id'}<input class="layui-input layui-hide" type='hidden' value='{$id}' name='id'>{/notempty}
|
||||||
|
<div class="layui-form-item text-center">
|
||||||
|
<button class="layui-btn layui-btn-normal" type='submit'>保存数据</button>
|
||||||
|
<button class="layui-btn layui-btn-danger" type='button' data-confirm="确定要取消编辑吗?" data-close>取消编辑</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<script>
|
||||||
|
$('[name="imgs"]').uploadMultipleImage()
|
||||||
|
</script>
|
86
plugs/think-plugs-ticket/src/view/ticket_outer/index.html
Normal file
86
plugs/think-plugs-ticket/src/view/ticket_outer/index.html
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
{extend name="table"}
|
||||||
|
|
||||||
|
{block name="button"}
|
||||||
|
<!--{if auth("add")}-->
|
||||||
|
<button type="button" class="layui-btn layui-btn-sm layui-btn-disabled" data-modal='{:url("add")}' data-title="添加工单">添加工单</button>
|
||||||
|
<!--{/if}-->
|
||||||
|
{/block}
|
||||||
|
|
||||||
|
{block name="content"}
|
||||||
|
<div class="layui-tab">
|
||||||
|
<div class="layui-row">
|
||||||
|
<div class="layui-col">
|
||||||
|
<div class="article_list think-bg-white">
|
||||||
|
{include file='ticket_outer/index_search'}
|
||||||
|
<table class="layui-hide" data-url="{$request->url()}" data-target-search="form.form-search" id="ticketTable" lay-filter="ticketTable"></table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script type="text/html" id="toolbar">
|
||||||
|
<!--{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 auth("move")}-->
|
||||||
|
<a data-modal="{:url('move')}?ticket_id={{ d.id }}" data-height="80%" data-width="80%" class="layui-btn layui-btn-xs" title="流转">分配</a>
|
||||||
|
<!--{/if}-->
|
||||||
|
<!--{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}-->
|
||||||
|
<!--{if auth("remove")}-->
|
||||||
|
<a data-confirm="是否删除此工单?" data-action="{:url('remove')}" data-value="id#{{ d.id }}" 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 () {
|
||||||
|
$('#ticketTable').layTable({
|
||||||
|
height: 'full-250',
|
||||||
|
toolbar: true,
|
||||||
|
sort: {field: 'create_at', type: 'desc'},
|
||||||
|
title: '工单列表',
|
||||||
|
cols: [[
|
||||||
|
{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:'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:80, templet:function(item){
|
||||||
|
if(item.status == 0){
|
||||||
|
return '<span style="color:red;">正在处理</span>';
|
||||||
|
}else if(item.status == 1){
|
||||||
|
return '<span style="color:green;">已处理</span>';
|
||||||
|
}else{
|
||||||
|
return '<span style="color:gray;">已关闭</span>';
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
|
||||||
|
{fixed: 'right', title:'操作', toolbar: '#toolbar', width:200}
|
||||||
|
]],
|
||||||
|
page: true
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
{/block}
|
@ -0,0 +1,49 @@
|
|||||||
|
<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">
|
||||||
|
<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">
|
||||||
|
<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">
|
||||||
|
<input data-date-range name="last_activity_at" value="{:input('get.last_activity_at')}" placeholder="请选择最后操作时间" class="layui-input">
|
||||||
|
</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"></i> 搜 索</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</fieldset>
|
Reference in New Issue
Block a user