Merge remote-tracking branch 'origin/develop' into feature/hant

# Conflicts:
#	composer.json
#	composer.lock
This commit is contained in:
hant 2025-04-01 20:32:13 +08:00
commit 0a333ab742
50 changed files with 1939 additions and 239 deletions

View File

@ -0,0 +1,31 @@
<?php
namespace app\admin\behavior;
use think\Lang;
class OrderDispatchLog
{
//记录订单任务日志
public function run(&$response)
{
Lang::load(APP_PATH . 'admin/lang/zh-cn/orders/dispatch2.php');
$Model = new \app\admin\model\OrderDispatch();
$statusList = $Model->getStatusList();
$dispatch = $response['dispatch']; //订单对象
$remark = $response['remark'] ?? ''; //备注
$data = [
'dispatch_id' => $dispatch->id,
'order_id' => $dispatch->order_id,
'worker_id' => $dispatch->worker_id,
'order_status' => $dispatch->status,
'order_status_text' => $statusList[$dispatch->status],
'remark' => $remark,
];
\app\admin\model\OrderDispatchLog::create($data);
//(new \app\admin\model\OrderDispatchLog())->cre($data);
}
}

View File

@ -27,7 +27,7 @@ class OrderLog
'role' => $role,
'remark' => $remark,
'admin_id' => $auth->id ?? 0,
'admin_user' => $role==1 ? $auth->nickname : $auth->name
'admin_user' => $role==1 ? ($auth->nickname ?? 'sys') : $auth->name
];
(new \app\admin\model\OrderLog())->save($data);
}

View File

@ -0,0 +1,24 @@
<?php
namespace app\admin\behavior;
use app\admin\model\OrderDispatch;
use think\Exception;
use think\Lang;
class SendOverTimeSms
{
//发短信通知
public function run(&$response)
{
//todo...
try {
$dispatch = $response['dispatch'];
if($dispatch->status == OrderDispatch::STATUS_OVERTIME){ //发送短信
}
}catch (Exception $exception){
}
}
}

View File

@ -31,6 +31,7 @@ class Auditorder extends Backend
$this->model = new \app\admin\model\Order();
//$this->view->assign("statusList", $this->model->getStatusList());
$this->view->assign("statusList", $this->model->getAuditStatusList());
$this->view->assign("offlineTotalTypeList", $this->model->getOfflineTotalTypeList());
}

View File

@ -30,6 +30,8 @@ class Configorder extends Backend
parent::_initialize();
$this->model = new Order();
$this->view->assign("statusList", $this->model->getStatusList());
$this->view->assign("offlineTotalTypeList", $this->model->getOfflineTotalTypeList());
}
@ -56,9 +58,10 @@ class Configorder extends Backend
return $this->selectpage();
}
list($where, $sort, $order, $offset, $limit) = $this->buildparams();
$list = $this->model
->scope('tab',Order::TAB_SETTING)
->tab(Order::TAB_SETTING)
->auth($this->auth,'dispatch_admin_id')
->areaauth($this->auth)
->with(['dispatch'])
->where($where)
->order($sort, $order)
@ -121,18 +124,20 @@ class Configorder extends Backend
$data = [
'status' => Order::STATUS_AUDITING,
'online_amount_last' => $params['online_amount_last'],
'offline_amount' => $params['offline_amount'],
'refund_amount' => $params['refund_amount'],
'cost' => $params['cost'],
];
$data['total'] = bcadd($row->online_amount,$params['offline_amount'],2);
$data['real_amount'] = bcdiv($data['total'],$params['refund_amount'],2);
$data['performance'] = bcdiv($data['real_amount'],$params['cost'],2);
$last_amount = bcadd($params['online_amount_last'],$params['offline_amount'],2);
$data['total'] = bcadd($row->online_amount,$last_amount,2);
$data['real_amount'] = bcsub($data['total'],$params['refund_amount'],2);
$data['performance'] = bcsub($data['real_amount'],$params['cost'],2);
$result = $row->allowField(true)->save($data);
//日志
$params['order'] = $row;
$params['role'] = 1;
$params['auth'] = $this->auth;

View File

@ -4,6 +4,7 @@ namespace app\admin\controller\orders;
use app\admin\model\Order;
use app\admin\model\OrderDispatch;
use app\admin\model\OrderDispatchLog;
use app\common\controller\Backend;
use app\common\Logic\OrderLogic;
use think\Db;
@ -14,8 +15,6 @@ use think\exception\DbException;
use think\exception\PDOException;
use think\exception\ValidateException;
use think\Hook;
use think\Lang;
use think\Loader;
/**
* 派单列管理
@ -31,7 +30,7 @@ class Dispatch2 extends Backend
*/
protected $model = null;
protected $searchFields = 'order.order_no,order.tel,order.customer,worker_name,worker_tel';
protected $searchFields = 'order.id,order.order_no,order.tel,order.customer,worker_name,worker_tel';
public function _initialize()
{
@ -41,8 +40,7 @@ class Dispatch2 extends Backend
$this->model = new \app\admin\model\OrderDispatch;
$this->view->assign("typeList", $this->model->getTypeList());
$this->view->assign("statusList", $this->model->getStatusList());
$this->view->assign("offlineTotalTypeList", $this->model->getOfflineTotalTypeList());
}
@ -72,6 +70,7 @@ class Dispatch2 extends Backend
$list = $this->model
->with(['order'])
->auth($this->auth)
->where($where)
->order($sort, $order)
->paginate($limit);
@ -82,6 +81,8 @@ class Dispatch2 extends Backend
$row->btn_abnormal = (in_array($row->status, $this->model->btnActiveStatusList('btn_abnormal'))) ? true : false;
$row->btn_finished = (in_array($row->status, $this->model->btnActiveStatusList('btn_finished'))) ? true : false;
$row->is_disabled = (in_array($row->status, $this->model->btnActiveStatusList('disabled_status'))) ? true : false;
$row->btn_record = (in_array($row->status, $this->model->btnActiveStatusList('btn_record'))) ? true : false;
// $row->btn_income = (in_array($row->status, $this->model->btnActiveStatusList('btn_income')) && in_array($row->order->status, $orderModel->incomeBtnStatus())) ? true : false;
}
$result = array("total" => $list->total(), "rows" => $list->items());
@ -92,88 +93,6 @@ class Dispatch2 extends Backend
}
/**
* 添加
*
* @return string
* @throws \think\Exception
*/
public function add()
{
if (false === $this->request->isPost()) {
$id = $this->request->param('order_id');
$order = model('order')->where('id', $id)->find();
if (!$order) {
$this->error(__('No results were found'));
}
$items = Db::name('item')
->where('status',1)
->field(['id','title','key_word','pid'])
->order('pid','asc')
->order('sort','desc')
->select();
$tree = $this->buildTree($items);
$formattedTree = $this->formatTree($tree);
$area_name = model('area')->getNameByCode($order->area_id);
$order->area_name = str_replace(',','/',$area_name);
$this->view->assign('items', $formattedTree);
$this->view->assign('row', $order);
return $this->view->fetch();
}
$params = $this->request->post('row/a');
if (empty($params)) {
$this->error(__('Parameter %s can not be empty', ''));
}
$params = $this->preExcludeFields($params);
if ($this->dataLimit && $this->dataLimitFieldAutoFill) {
$params[$this->dataLimitField] = $this->auth->id;
}
$result = false;
Db::startTrans();
try {
//是否采用模型验证
if ($this->modelValidate) {
$name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
$validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : $name) : $this->modelValidate;
$this->model->validateFailException()->validate($validate);
}
$order = model('order')->where('id',$params['order_id'])->find();
if (!$order){
$this->error(__('No results were found'));
}
$insert = [
'admin_id' => $this->auth->id,
'admin_user' => $this->auth->nickname,
'order_id' => $params['order_id'],
'type' => 1,
'worker_id' => $params['worker_id'],
'plan_time' => $order['plan_time'],
'is_receipt' => $order['receive_type'] == 1
];
$worker = model('worker')->where('id',$params['worker_id'])->find();
$insert ['worker_name'] = $worker->name;
$insert ['worker_tel'] = $worker->tel;
$result = $this->model->allowField(true)->save($insert);
$order->status = Order::STATUS_DISPATCHED;
$order->save();
Db::commit();
} catch (ValidateException | PDOException | Exception $e) {
Db::rollback();
$this->error($e->getMessage());
}
if ($result === false) {
$this->error(__('No rows were inserted'));
}
$this->success();
}
/**
* 编辑
*
@ -188,12 +107,20 @@ class Dispatch2 extends Backend
if (!$row) {
$this->error(__('No Results were found'));
}
$order = Order::where('id',$row->id)->with(['area'])->find();
if(empty($order)){
$this->error(__('未找到关联订单'));
}
$adminIds = $this->getDataLimitAdminIds();
if (is_array($adminIds) && !in_array($row[$this->dataLimitField], $adminIds)) {
$this->error(__('You have no permission'));
}
if (false === $this->request->isPost()) {
$this->view->assign('row', $row);
$this->view->assign('order', $order);
return $this->view->fetch();
}
@ -207,6 +134,10 @@ class Dispatch2 extends Backend
if (empty($params)) {
$this->error(__('Parameter %s can not be empty', ''));
}
if(!in_array($row->status ,$this->model->btnActiveStatusList('btn_edit'))){
$this->error(__('任务状态已变更,请刷新后再操作'));
}
$params = $this->preExcludeFields($params);
$result = false;
Db::startTrans();
@ -217,7 +148,28 @@ class Dispatch2 extends Backend
$validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.edit' : $name) : $this->modelValidate;
$row->validateFailException()->validate($validate);
}
$workerChange = false;
$remark = '';
if($row->worker_id != $params['worker_id']){ //更换了师傅
$worker = model('worker')->where('id',$params['worker_id'])->find();
$params ['worker_name'] = $worker->name;
$params ['worker_tel'] = $worker->tel;
//记录日志
$remark = '师傅由 ('.$row->worker_id.')'.$row->worker_name.' 更换为('.$params['worker_id'].')'.$worker->name;
$workerChange = true;
}
$result = $row->allowField(true)->save($params);
if($workerChange){
$hookParams = [
'dispatch' => $row,
'remark' => $remark,
];
Hook::listen('order_dispatch_change', $hookParams);
}
Db::commit();
} catch (ValidateException | PDOException | Exception $e) {
Db::rollback();
@ -288,13 +240,14 @@ class Dispatch2 extends Backend
$validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.edit' : $name) : $this->modelValidate;
$row->validateFailException()->validate($validate);
}
$params['status'] = OrderDispatch::STATUS_FINISH;
$params['finish_time'] = date('Y-m-d H:i:s');
$result = $row->allowField(true)->save($params);
//修改订单状态
$OrderLogic = new OrderLogic();
$OrderLogic -> dispachFinishAfter($row,['role'=>1,'auth'=>$this->auth]);
$OrderLogic -> dispachFinishAfter($row,['role'=>1,'auth'=>$this->auth,'remark'=>'后台操作adminId:'.$this->auth->id]);
Db::commit();
} catch (ValidateException | PDOException | Exception $e) {
Db::rollback();
@ -401,6 +354,9 @@ class Dispatch2 extends Backend
$remark = $reason;
$count = 0;
$OrderLogic = new OrderLogic();
Db::startTrans();
try {
foreach ($list as $item) {
@ -410,17 +366,19 @@ class Dispatch2 extends Backend
$this->error('订单状态已变更,请刷新后操作');
}
//取消
$item->save(['status' => OrderDispatch::STATUS_CANCEL, 'remark' => $remark]);
// $item->allowField(true)->save(['status' => OrderDispatch::STATUS_CANCEL, 'remark' => $remark]);
//回退订单状态
$order->allowField(true)->save(['status' => Order::STATUS_DISPATCHING]);
$params['order'] = $order;
$params['role'] = 1;
$params['auth'] = $this->auth;
$params['remark'] = '派单被取消[ID' . $item->id . '],订单状态回退';
if (!empty($remark)) {
$params['remark'] .= ',操作备注:' . $remark;
}
Hook::listen('order_change', $params);
//$order->allowField(true)->save(['status' => Order::STATUS_DISPATCHING]);
/* Hook::listen('order_change', $params);
$hookParams = [
'dispatch' => $item,
'remark' => '后台取消,adminId:'.$this->auth->id
];
Hook::listen('order_dispatch_change', $hookParams);*/
$OrderLogic->cancelOrderDispatch($item,$this->auth,$remark);
}
Db::commit();
} catch (PDOException | Exception $e) {

View File

@ -0,0 +1,148 @@
<?php
namespace app\admin\controller\orders;
use app\admin\model\OrderDispatch;
use app\common\controller\Backend;
use think\Db;
use think\Exception;
use think\exception\DbException;
use think\exception\PDOException;
use think\exception\ValidateException;
/**
* 任务记录
*
* @icon fa fa-circle-o
*/
class Dispatchrecord extends Backend
{
/**
* OrderDispatchRecord模型对象
* @var \app\admin\model\OrderDispatchRecord
*/
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->model = new \app\admin\model\OrderDispatchRecord;
$this->view->assign("needNoticeList", $this->model->getNeedNoticeList());
$this->view->assign("statusList", $this->model->getStatusList());
}
/**
* 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
* 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
* 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
*/
/**
* 添加
*
* @return string
* @throws \think\Exception
*/
public function add($ids=null)
{
if (false === $this->request->isPost()) {
$dispatch = OrderDispatch::get($ids);
if(empty($dispatch)){
$this->error('没有关联派单');
}
$list = $this->model->where('dispatch_id',$ids)->order('id','desc')->select();
$this->assign('dispatch',$dispatch);
$this->assign('records',$list);
return $this->view->fetch();
}
$params = $this->request->post('row/a');
if (empty($params)) {
$this->error(__('Parameter %s can not be empty', ''));
}
$params = $this->preExcludeFields($params);
if ($this->dataLimit && $this->dataLimitFieldAutoFill) {
$params[$this->dataLimitField] = $this->auth->id;
}
$result = false;
Db::startTrans();
try {
//是否采用模型验证
if ($this->modelValidate) {
$name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
$validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : $name) : $this->modelValidate;
$this->model->validateFailException()->validate($validate);
}
$params['admin_id'] = $this->auth->id;
$result = $this->model->allowField(true)->save($params);
Db::commit();
} catch (ValidateException|PDOException|Exception $e) {
Db::rollback();
$this->error($e->getMessage());
}
if ($result === false) {
$this->error(__('No rows were inserted'));
}
$this->success();
}
/**
* 编辑
*
* @param $ids
* @return string
* @throws DbException
* @throws \think\Exception
*/
public function edit($ids = null)
{
$row = $this->model->get($ids);
if (!$row) {
$this->error(__('No Results were found'));
}
$adminIds = $this->getDataLimitAdminIds();
if (is_array($adminIds) && !in_array($row[$this->dataLimitField], $adminIds)) {
$this->error(__('You have no permission'));
}
if (false === $this->request->isPost()) {
$this->view->assign('row', $row);
return $this->view->fetch();
}
$params = $this->request->post('row/a');
if (empty($params)) {
$this->error(__('Parameter %s can not be empty', ''));
}
$params = $this->preExcludeFields($params);
$result = false;
Db::startTrans();
try {
//是否采用模型验证
if ($this->modelValidate) {
$name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
$validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.edit' : $name) : $this->modelValidate;
$row->validateFailException()->validate($validate);
}
$result = $row->allowField(true)->save($params);
Db::commit();
} catch (ValidateException|PDOException|Exception $e) {
Db::rollback();
$this->error($e->getMessage());
}
if (false === $result) {
$this->error(__('No rows were updated'));
}
$this->success();
}
}

View File

@ -3,7 +3,7 @@
return [
'Id' => 'ID',
'Order_id' => '订单ID',
'Order_no' => '订单号',
'Order_no' => '订单号',
'Tel' => '客户手机',
'Item_type' => '收款事项',
'Item_type 1' => '定金',
@ -13,7 +13,7 @@ return [
'Amount' => '收款金额',
'Income_type' => '收款方式',
'Income_type 1' => '平台收款',
'Income_type 2' => '线下款',
'Income_type 2' => '线下款',
'Admin_id' => '创建人ID',
'Admin_user' => '创建人',
'Payment_time' => '收款时间',

View File

@ -21,7 +21,7 @@ return [
'From 1' => '师傅',
'From 2' => '顾客',
'From 3' => '平台',
'Refund_amount' => '退款金额',
'Refund_amount' => '退款金额',
'Company_refund_amount' => '公司退款金额',
'Worker_refund_amount' => '师傅退款金额',
'Refund_type' => '退款方式',
@ -45,7 +45,7 @@ return [
'Handle_admin_user' => '处理人',
'Star' => '评分',
'Order.id' => 'ID',
'Order.order_no' => '订单号',
'Order.order_no' => '订单号',
'Order.customer' => '客户姓名',
'Order.tel' => '客户电话',
'Order.status' => '订单状态',

View File

@ -2,7 +2,7 @@
return [
'Id' => 'ID',
'Order_no' => '订单号',
'Order_no' => '订单号',
'Customer' => '客户姓名',
'Tel' => '客户电话',
'Status' => '订单状态',
@ -61,4 +61,8 @@ return [
'Dispatch_time' => '派单时间',
'Delete_time' => '删除时间',
'Coupons' => '优惠',
'Offline_amount_type' => '线下尾款类型',
'Offline_amount_type 0' => '无',
'Offline_amount_type 1' => '师傅收',
'Offline_amount_type 2' => '公司收',
];

View File

@ -21,7 +21,7 @@ return [
'Create_time' => '创建时间',
'Update_time' => '编辑时间',
'Order.id' => 'ID',
'Order.order_no' => '订单号',
'Order.order_no' => '订单号',
'Order.customer' => '客户姓名',
'Order.tel' => '客户电话',
'Order.status' => '订单状态',

View File

@ -3,7 +3,7 @@
return [
'Id' => 'ID',
'User_id' => '用户ID',
'Order_no' => '订单号',
'Order_no' => '订单号',
'Customer' => '客户姓名',
'Tel' => '客户电话',
'Status' => '订单状态',
@ -36,11 +36,18 @@ return [
'Detail' => '订单详情',
'Remark' => '订单备注',
'Images' => '图片',
'Plan_time' => '客户预约时间',
'Plan_time' => '预约时间',
'Admin_id' => '录单员ID',
'Total' => '总收款',
'Online_amount' => '线上收款',
'Offline_amount' => '线下收款',
'Online_amount' => '线上预付',
'Online_amount_last' => '线上尾款',
'Offline_amount_type' => '线下尾款类型',
'Offline_amount_type 0' => '无',
'Offline_amount_type 1' => '师傅收',
'Offline_amount_type 2' => '公司收',
'Offline_amount' => '线下尾款',
'Discount_amount' => '优惠抵扣',
'Real_amount' => '实际收款',
'Refund_amount' => '退款金额',

View File

@ -2,7 +2,7 @@
return [
'Id' => 'ID',
'Order_no' => '订单号',
'Order_no' => '订单号',
'Customer' => '客户姓名',
'Tel' => '客户电话',
'Status' => '订单状态',
@ -35,14 +35,20 @@ return [
'Detail' => '订单详情',
'Remark' => '订单备注',
'Images' => '图片',
'Plan_time' => '客户预约时间',
'Plan_time' => '预约时间',
'Admin_id' => '录单员ID',
'Coupon_id' => '优惠码id',
'Total' => '总收款',
'Online_amount' => '线上收款',
'Offline_amount' => '线下收款',
'Online_amount' => '线上预付',
'Online_amount_last' => '线上尾款',
'Offline_amount' => '线下尾款',
'Offline_amount_type' => '线下尾款类型',
'Offline_amount_type 0' => '无',
'Offline_amount_type 1' => '师傅收',
'Offline_amount_type 2' => '公司收',
'Discount_amount' => '优惠抵扣',
'Refund_amount' => '总退款额',
'Refund_amount' => '退款额',
'Real_amount' => '实际收款',
'Cost' => '师傅成本',
'Performance' => '预计利润',

View File

@ -36,7 +36,7 @@ return [
'Create_time' => '派单时间',
'Update_time' => '编辑时间',
'Order.id' => 'ID',
'Order.order_no' => '订单号',
'Order.order_no' => '订单号',
'Order.customer' => '客户姓名',
'Order.tel' => '客户电话',
'Order.status' => '订单状态',
@ -61,14 +61,14 @@ return [
'Order.detail' => '订单详情',
'Order.remark' => '订单备注',
'Order.images' => '图片',
'Order.plan_time' => '客户预约时间',
'Order.plan_time' => '预约时间',
'Order.admin_id' => '录单员ID',
'Order.coupon_id' => '优惠码id',
'Order.total' => '总收款',
'Order.online_amount' => '线上收款',
'Order.offline_amount' => '线下款',
'Order.online_amount' => '线上预付',
'Order.offline_amount' => '线下款',
'Order.discount_amount' => '优惠抵扣',
'Order.refund_amount' => '退款额',
'Order.refund_amount' => '退款额',
'Order.real_amount' => '实际收款',
'Order.cost' => '师傅成本',
'Order.performance' => '预计利润',

View File

@ -27,6 +27,13 @@ return [
'Set status to -20' => '设为已移交',
'Status -30' => '已取消',
'Set status to -30' => '设为已取消',
'Total' => '线下尾款',
'Online' => '线上尾款',
'Amount' => '预计佣金',
'Offline_total_type' => '线下尾款类型',
'Offline_total_type 0' => '无',
'Offline_total_type 1' => '师傅收',
'Offline_total_type 2' => '公司收',
'Remark' => '备注',
'Notice_num' => '通知次数',
'Plan_time' => '预约时间',
@ -34,9 +41,9 @@ return [
'Admin_id' => '派单人ID',
'Admin_user' => '派单人',
'Create_time' => '派单时间',
'Update_time' => '编辑时间',
'Update_time' => '更新时间',
'Order.id' => 'ID',
'Order.order_no' => '订单号',
'Order.order_no' => '订单号',
'Order.customer' => '客户姓名',
'Order.tel' => '客户电话',
'Order.status' => '订单状态',
@ -61,14 +68,14 @@ return [
'Order.detail' => '订单详情',
'Order.remark' => '订单备注',
'Order.images' => '图片',
'Order.plan_time' => '客户预约时间',
'Order.plan_time' => '预约时间',
'Order.admin_id' => '录单员ID',
'Order.coupon_id' => '优惠码id',
'Order.total' => '总收款',
'Order.online_amount' => '线上收款',
'Order.offline_amount' => '线下款',
'Order.online_amount' => '线上预付',
'Order.offline_amount' => '线下款',
'Order.discount_amount' => '优惠抵扣',
'Order.refund_amount' => '退款额',
'Order.refund_amount' => '退款额',
'Order.real_amount' => '实际收款',
'Order.cost' => '师傅成本',
'Order.performance' => '预计利润',

View File

@ -0,0 +1,19 @@
<?php
return [
'Dispatch_id' => '任务ID',
'Worker_id' => '师傅ID',
'Remark' => '备注',
'Need_notice' => '提醒师傅',
'Need_notice 0' => '不需要',
'Need_notice 1' => '需要',
'Status' => '通知状态',
'Status 0' => '未通知',
'Set status to 0'=> '设为未通知',
'Status 1' => '已通知',
'Set status to 1'=> '设为已通知',
'Notice_time' => '提醒时间',
'Create_time' => '创建时间',
'Update_time' => '更新时间',
'Admin_id' => '管理员ID'
];

View File

@ -3,7 +3,7 @@
return [
'Id' => 'ID',
'Order_id' => '订单ID',
'Order_no' => '订单号',
'Order_no' => '订单号',
'Tel' => '客户手机',
'Item_type' => '收款事项',
'Item_type 1' => '定金',
@ -19,7 +19,7 @@ return [
'Amount' => '收款金额',
'Income_type' => '收款方式',
'Income_type 1' => '平台收款',
'Income_type 2' => '线下款',
'Income_type 2' => '线下款',
'Admin_id' => '创建人ID',
'Admin_user' => '创建人',
'Payment_time' => '收款时间',

View File

@ -12,7 +12,7 @@ return [
'Remark' => '备注',
'Create_time' => '创建时间',
'Order.id' => 'ID',
'Order.order_no' => '订单号',
'Order.order_no' => '订单号',
'Order.customer' => '客户姓名',
'Order.tel' => '客户电话',
'Order.status' => '订单状态',

View File

@ -2,7 +2,7 @@
return [
'Id' => 'ID',
'Order_no' => '订单号',
'Order_no' => '订单号',
'Customer' => '客户姓名',
'Tel' => '客户电话',
'Status' => '订单状态',
@ -35,7 +35,7 @@ return [
'Detail' => '订单详情',
'Remark' => '订单备注',
'Images' => '图片',
'Plan_time' => '客户预约时间',
'Plan_time' => '预约时间',
'Admin_id' => '录单员ID',
'Total' => '总收款',
'Cost' => '师傅成本',

View File

@ -2,6 +2,7 @@
namespace app\admin\model;
use app\admin\library\Auth;
use think\Model;
use traits\model\SoftDelete;
@ -29,7 +30,8 @@ class Order extends Model
protected $append = [
'status_text',
'collect_text',
'dispatch_type_text'
'dispatch_type_text',
'offline_amount_type_text'
];
@ -75,6 +77,12 @@ class Order extends Model
}
public function getOfflineTotalTypeList()
{
return ['0' => __('Offline_amount_type 0'), '1'=> __('Offline_amount_type 1'),'2' => __('Offline_amount_type 2')];
}
public function getStatusTextAttr($value, $data)
{
$value = $value ?: ($data['status'] ?? '');
@ -82,6 +90,16 @@ class Order extends Model
return $list[$value] ?? '';
}
public function getOfflineAmountTypeTextAttr($value, $data)
{
$value = $value ?: ($data['offline_amount_type'] ?? '');
$list = $this->getOfflineTotalTypeList();
return $list[$value] ?? '';
}
public function getCollectTextAttr($value, $data)
{
@ -158,4 +176,38 @@ class Order extends Model
{
return $this->hasOne(OrderDispatch::class, 'order_id', 'id', [], 'LEFT')->setEagerlyType(0)->where('fa_order_dispatch.status',OrderDispatch::STATUS_FINISH);
}
/**
* 管理员权限
* @param $query
* @param Auth $auth
* @param string $auth_admin_id
* @return mixed
*/
public function scopeAuth($query, Auth $auth, string $admin_id_field='admin_id'){
if(!$auth->isSuperAdmin()){
$query->where('fa_order.'.$admin_id_field,$auth->id);
}
return $query;
}
/**
* 地域权限
* @param $query
* @param Auth $auth
* @param string $area_id_field
* @return mixed
*/
public function scopeAreaauth($query,Auth $auth,string $area_id_field='area_id'){
if(!$auth->isSuperAdmin()){
$areaIds = array_unique(array_filter(explode(',',trim($auth->area_ids))));
if(!in_array('*',$areaIds)){
$query->whereIn('fa_order.'.$area_id_field,$areaIds);
}
}
return $query;
}
}

View File

@ -2,6 +2,7 @@
namespace app\admin\model;
use app\admin\library\Auth;
use think\Model;
@ -38,7 +39,7 @@ class OrderDispatch extends Model
const STATUS_CLOCK = 30; //已打卡
const STATUS_FINISH = 60; //完成
const STATUS_REFUSED = -10; //拒绝
const STATUS_MOVE = -20; //中转
const STATUS_MOVE = -20; //中转(状态废弃)
const STATUS_CANCEL = -30; //取消
@ -49,7 +50,9 @@ class OrderDispatch extends Model
public function getStatusList()
{
return ['0' => __('Status 0'), '10' => __('Status 10'), '20' => __('Status 20'),'25' => __('Status 25'), '30' => __('Status 30'), '60' => __('Status 60'), '-10' => __('Status -10'), '-20' => __('Status -20'), '-30' => __('Status -30')];
return ['0' => __('Status 0'), '10' => __('Status 10'), '20' => __('Status 20'),'25' => __('Status 25'), '30' => __('Status 30'), '60' => __('Status 60'), '-10' => __('Status -10'),
// '-20' => __('Status -20'),
'-30' => __('Status -30')];
}
public function getIsNoticeList()
@ -57,6 +60,11 @@ class OrderDispatch extends Model
return ['0' => __('Is_notice 0'), '1' => __('Is_notice 1')];
}
public function getOfflineTotalTypeList()
{
return ['0' => __('Offline_total_type 0'), '1'=> __('Offline_total_type 1'),'2' => __('Offline_total_type 2')];
}
public function getTypeTextAttr($value, $data)
{
@ -144,9 +152,34 @@ class OrderDispatch extends Model
self::STATUS_CANCEL,
self::STATUS_REFUSED,
self::STATUS_MOVE
]
],
'btn_record' => [
self::STATUS_TOGET,
self::STATUS_GOTIT,
self::STATUS_PLANIT,
self::STATUS_OVERTIME,
self::STATUS_CLOCK,
],
];
return $btns[$btn]??[];
}
/**
* 管理员权限
* @param $query
* @param Auth $auth
* @param string $auth_admin_id
* @return mixed
*/
public function scopeAuth($query, Auth $auth, string $admin_id_field='admin_id'){
if(!$auth->isSuperAdmin()){
$query->where('fa_order_dispatch.'.$admin_id_field,$auth->id);
}
return $query;
}
}

View File

@ -0,0 +1,36 @@
<?php
namespace app\admin\model;
use think\Model;
class OrderDispatchLog extends Model
{
// 表名
protected $name = 'order_dispatch_log';
// 自动写入时间戳字段
protected $autoWriteTimestamp = 'datetime';
protected $dateFormat = 'Y-m-d H:i:s';
// 定义时间戳字段名
protected $createTime = 'create_time';
protected $updateTime = false;
protected $deleteTime = false;
// 追加属性
protected $append = [
'order_status_text'
];
}

View File

@ -0,0 +1,64 @@
<?php
namespace app\admin\model;
use think\Model;
class OrderDispatchRecord extends Model
{
// 表名
protected $name = 'order_dispatch_record';
// 自动写入时间戳字段
protected $autoWriteTimestamp = 'datetime';
protected $dateFormat = 'Y-m-d H:i:s';
// 定义时间戳字段名
protected $createTime = 'create_time';
protected $updateTime = 'update_time';
protected $deleteTime = false;
// 追加属性
protected $append = [
'need_notice_text',
'status_text'
];
public function getNeedNoticeList()
{
return ['0' => __('Need_notice 0'), '1' => __('Need_notice 1')];
}
public function getStatusList()
{
return ['0' => __('Status 0'), '1' => __('Status 1')];
}
public function getNeedNoticeTextAttr($value, $data)
{
$value = $value ?: ($data['need_notice'] ?? '');
$list = $this->getNeedNoticeList();
return $list[$value] ?? '';
}
public function getStatusTextAttr($value, $data)
{
$value = $value ?: ($data['status'] ?? '');
$list = $this->getStatusList();
return $list[$value] ?? '';
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace app\admin\validate;
use think\Validate;
class OrderDispatchRecord extends Validate
{
/**
* 验证规则
*/
protected $rule = [
];
/**
* 提示消息
*/
protected $message = [
];
/**
* 验证场景
*/
protected $scene = [
'add' => [],
'edit' => [],
];
}

View File

@ -3,7 +3,7 @@
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Order_id')}:</label>
<div class="col-xs-12 col-sm-8">
<input placeholder="选择订单号" id="c-order_id" data-field="order_no" data-rule="required" data-source="order/index" class="form-control selectpage" name="row[order_id]" type="text" value="{$row.order_id|htmlentities}">
<input placeholder="选择订单号" id="c-order_id" data-field="order_no" data-rule="required" data-source="order/index" class="form-control selectpage" name="row[order_id]" type="text" value="{$row.order_id|htmlentities}">
</div>
</div>

View File

@ -92,6 +92,14 @@
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Total')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-total" readonly data-rule="required" class="form-control" step="0.01" name="row[total]" type="number" value="{$row.total|htmlentities}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Online_amount')}:</label>
<div class="col-xs-12 col-sm-8">
@ -99,6 +107,13 @@
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Online_amount_last')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-online_amount_last" data-rule="required" class="form-control" step="0.01" name="row[online_amount_last]" type="number" value="{$row.online_amount_last|htmlentities}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Offline_amount')}:</label>
<div class="col-xs-12 col-sm-8">
@ -106,10 +121,11 @@
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Total')}:</label>
<label class="control-label col-xs-12 col-sm-2">{:__('Offline_amount_type')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-total" readonly data-rule="required" class="form-control" step="0.01" name="row[total]" type="number" value="{$row.total|htmlentities}">
{:build_select('offline_amount_type',$offlineTotalTypeList,$row['dispatch']['offline_total_type'],['class'=>'form-control','data-rule'=>'required'])}
</div>
</div>

View File

@ -1,5 +1,16 @@
<form id="edit-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
{notempty name='row.audit_remark'}
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Audit_remark')}:</label>
<div class="col-xs-12 col-sm-8">
<div class="alert alert-danger">{$row.audit_remark|htmlentities}</div>
</div>
</div>
{/notempty}
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Order_no')}:</label>
<div class="col-xs-12 col-sm-8">
@ -38,10 +49,24 @@
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Online_amount_last')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-online_amount_last" data-rule="required" class="form-control" step="0.01" name="row[online_amount_last]" type="number" value="{$row.dispatch.online_amount|htmlentities}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Offline_amount')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-offline_amount" class="form-control" step="0.01" name="row[offline_amount]" type="number" value="{$row.offline_amount|htmlentities}">
<input id="c-offline_amount" data-rule="required" class="form-control" step="0.01" name="row[offline_amount]" type="number" value="{$row.dispatch.total|htmlentities}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Offline_amount_type')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_select('offline_amount_type',$offlineTotalTypeList,$row['dispatch']['offline_total_type'],['class'=>'form-control','data-rule'=>'required'])}
</div>
</div>
@ -52,31 +77,21 @@
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Cost')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-cost" data-rule="required" class="form-control" step="0.01" name="row[cost]" type="number" value="{$row.cost|htmlentities}">
<input id="c-cost" data-rule="required" class="form-control" step="0.01" name="row[cost]" type="number" value="{$row.dispatch.amount|htmlentities}">
</div>
</div>
<div class="form-group">
<!-- <div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Performance')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-performance" readonly class="form-control" step="0.01" type="number" value="{$row.performance|htmlentities}">
</div>
</div>
{notempty name='row.audit_admin_id'}
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Audit_remark')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-Audit_remark" readonly class="form-control" type="text" value="{$row.audit_remark|htmlentities}">
</div>
</div>
{/notempty}
-->
<div class="form-group layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>

View File

@ -13,7 +13,7 @@
<p><strong>订单详情:</strong> {$row.detail}</p>
<p><strong>订单备注:</strong> {$row.remark}</p>
<!-- <p><strong>收款方式:</strong> {$row.receive_type == 1 ? '定金':'全款'}</p>-->
<!-- <p><strong>线上收款:</strong> {$row.online_amount}</p>-->
<!-- <p><strong>线上预付:</strong> {$row.online_amount}</p>-->
</div>
<form id="add-form" class="form-horizontal col-xs-12" role="form" data-toggle="validator" method="POST" action="">
<div class="form-group">

View File

@ -13,7 +13,7 @@
<p><strong>订单详情:</strong> {$row.detail}</p>
<p><strong>订单备注:</strong> {$row.remark}</p>
<!-- <p><strong>收款方式:</strong> {$row.receive_type == 1 ? '定金':'全款'}</p>-->
<!-- <p><strong>线上收款:</strong> {$row.online_amount}</p>-->
<!-- <p><strong>线上预付:</strong> {$row.online_amount}</p>-->
</div>
<form id="add-form" class="form-horizontal col-xs-12" role="form" data-toggle="validator" method="POST" action="">
<div class="form-group">

View File

@ -8,23 +8,13 @@
<!-- </div>-->
{notempty name ='action'}
<input name="row[action]" type="hidden" value="{$action|htmlentities}">
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('订单号')}:</label>
<label class="control-label col-xs-12 col-sm-2">{:__('订单编号')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-order_no" readonly class="form-control" data-field="order_no" type="text" value="{$order.order_no|htmlentities}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('服务')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-item_title" readonly class="form-control" type="text" value="{$order.item_title|htmlentities}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('客户姓名')}:</label>
@ -33,20 +23,37 @@
</div>
</div>
<!-- <div class="form-group">-->
<!-- <label class="control-label col-xs-12 col-sm-2">{:__('客户电话')}:</label>-->
<!-- <div class="col-xs-12 col-sm-8">-->
<!-- <input id="c-tel" readonly class="form-control" type="text" value="{$order.tel|htmlentities}">-->
<!-- </div>-->
<!-- </div>-->
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('客户电话')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-tel" readonly class="form-control" type="text" value="{$order.tel|htmlentities}">
</div>
</div>
<!-- <div class="form-group">-->
<!-- <label class="control-label col-xs-12 col-sm-2">{:__('客户地址')}:</label>-->
<!-- <div class="col-xs-12 col-sm-8">-->
<!-- <input id="c-address" readonly class="form-control" type="text" value="{$order.address|htmlentities}">-->
<!-- </div>-->
<!-- </div>-->
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('客户地址')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-address" readonly class="form-control" type="text" value="{$order.area.short_merge_name|htmlentities} {$order.address|htmlentities}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('服务类目')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-item_title" readonly class="form-control" type="text" value="{$order.item_title|htmlentities}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Order.detail')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-detail" readonly class="form-control" type="text" value="{$order.detail|htmlentities}">
</div>
</div>
{notempty name ='action'}
<input name="row[action]" type="hidden" value="{$action|htmlentities}">
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('当前师傅')}:</label>
@ -71,6 +78,15 @@
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('线上预付')}:</label>
<div class="col-xs-12 col-sm-8">
<input readonly type="text" class="form-control" value="{$order.online_amount|htmlentities}">
</div>
</div>
{if $row['is_receipt']==0 }
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('线上收款')}:</label>
<div class="col-xs-12 col-sm-8">
@ -78,11 +94,35 @@
</div>
</div>
{if $row['is_receipt'] }
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('尾款收款')}:</label>
<div class="col-xs-12 col-sm-8">
<input readonly class="form-control" type="text" value="无需收尾款">
</div>
</div>
{/if}
{if $row['is_receipt']==1 }
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('线下收款')}:</label>
<label class="control-label col-xs-12 col-sm-2">{:__('线上尾款')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-total" data-rule="required" placeholder="请输入线下收款金额" class="form-control" name="row[total]" type="number" min="0" value="{$row.total|htmlentities}">
<input name="row[online_total]" type="number" min="0" placeholder="请输入线上尾款金额" class="form-control" value="{$order.online_total|htmlentities}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('线下尾款')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-total" data-rule="required" placeholder="请输入线下尾款金额" class="form-control" name="row[total]" type="number" min="0" value="{$row.total|htmlentities}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Offline_amount_type')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_select('offline_total_type',$offlineTotalTypeList,$row['offline_total_type'],['class'=>'form-control','data-rule'=>'required'])}
</div>
</div>
@ -93,7 +133,7 @@
<input id="c-image" class="form-control" size="35" name="row[image]" type="text" value="">
<div class="input-group-addon no-border no-padding">
<span><button type="button" id="faupload-image" class="btn btn-danger faupload" data-input-id="c-image" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp" data-multiple="false" data-preview-id="p-image"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
<span><button type="button" id="fachoose-image" class="btn btn-primary fachoose" data-input-id="c-image" data-mimetype="image/*" data-multiple="false"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
<span><button type="button" id="fachoose-image" class="btn btn-primary fachoose" data-input-id="c-image" data-mimetype="image/*" data-multiple="true"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
</div>
<span class="msg-box n-right"></span>
</div>
@ -124,7 +164,7 @@
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Remark')}:</label>
<div class="col-xs-12 col-sm-8">
<textarea class="form-control" placeholder="备注" name="row[remark]" >{$row.remark|htmlentities}</textarea>
<textarea class="form-control" data-rule="required" placeholder="备注" name="row[remark]" >{$row.remark|htmlentities}</textarea>
</div>
</div>
@ -132,8 +172,7 @@
<div class="form-group layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('立即完成任务')}</button>
<span class="warning text-danger " style="font-size: 13px;margin-left:5px;" > 请确认无误后操作</span>
<button type="submit" class="btn btn-success btn-embossed disabled">{:__('立即完成任务')}</button>
</div>
</div>
@ -142,43 +181,40 @@
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Order_id')}:</label>
<label class="control-label col-xs-12 col-sm-2">{:__('当前进度')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-order_id" data-field="order_no" data-rule="required" data-source="order/index" class="form-control selectpage" name="row[order_id]" type="text" value="{$row.order_id|htmlentities}">
<input readonly type="text" class="form-control" value="{$row.status_text|htmlentities}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Worker_id')}:</label>
<label class="control-label col-xs-12 col-sm-2">{:__('当前师傅')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-worker_id" data-rule="required" data-field="name" data-source="workers/worker/index" class="form-control selectpage" name="row[worker_id]" type="text" value="{$row.worker_id|htmlentities}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Worker_name')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-worker_name" data-rule="required" class="form-control" name="row[worker_name]" type="text" value="{$row.worker_name|htmlentities}">
<input id="c-worker_id" placeholder="输入师傅名称,可手动选择更换" data-rule="required" data-field="name" data-source="workers/worker/index" class="form-control selectpage" name="row[worker_id]" type="text" value="{$row.worker_id|htmlentities}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Worker_tel')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-worker_tel" data-rule="required" class="form-control" name="row[worker_tel]" type="text" value="{$row.worker_tel|htmlentities}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
<label class="control-label col-xs-12 col-sm-2 text-left">{:__('预约时间')}:</label>
<div class="col-xs-12 col-sm-8">
<div class="radio">
{foreach name="statusList" item="vo"}
<label for="row[status]-{$key}"><input id="row[status]-{$key}" name="row[status]" type="radio" value="{$key}" {in name="key" value="$row.status"}checked{/in} /> {$vo}</label>
{/foreach}
</div>
<input id="c-plan_time" data-rule="required" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm" value="{$row.plan_time|htmlentities}" data-use-current="true" name="row[plan_time]" type="text" >
</div>
</div>
<div class="form-group layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
@ -187,8 +223,4 @@
</div>
{/notempty}
</form>

View File

@ -0,0 +1,75 @@
<form id="add-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action=""
xmlns="http://www.w3.org/1999/html">
{notempty name='records'}
<div class="col-xs-12 col-sm-6">
{/notempty}
<input type="hidden" name="row[dispatch_id]" value="{$dispatch.id|htmlentities}">
<input type="hidden" name="row[worker_id]" value="{$dispatch.worker_id|htmlentities}">
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Remark')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-remark" data-rule="required" class="form-control" name="row[remark]" type="text">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Need_notice')}:</label>
<div class="col-xs-12 col-sm-8">
<select id="c-need_notice" data-rule="required" class="form-control selectpicker" name="row[need_notice]">
{foreach name="needNoticeList" item="vo"}
<option value="{$key}" {in name="key" value="0"}selected{/in}>{$vo}</option>
{/foreach}
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Notice_time')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-notice_time" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-use-current="true" name="row[notice_time]" type="text" value="{:date('Y-m-d H:i:s')}">
</div>
</div>
{notempty name='records'}
</div>
{/notempty}
{notempty name='records'}
<div class="col-xs-12 col-sm-6">
<table class="table table-hover">
<thead>
<tr>
<th>ID</th>
<th>备忘内容</th>
<th>通知</th>
<th>状态</th>
<th>时间</th>
</tr>
</thead>
<tbody>
{volist name="records" id="item"}
<tr>
<td>{$item.id}</td>
<td>{$item.remark}</td>
<td>{$item.need_notice_text}</td>
<td>{$item.status_text}</td>
<td>{$item.create_time}</td>
</tr>
{/volist}
</tbody>
</table>
</div>
{/notempty}
<div class="form-group layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
</div>
</div>
</form>

View File

@ -0,0 +1,69 @@
<form id="edit-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Dispatch_id')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-dispatch_id" data-rule="required" data-source="dispatch/index" class="form-control selectpage" name="row[dispatch_id]" type="text" value="{$row.dispatch_id|htmlentities}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Worker_id')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-worker_id" data-rule="required" data-source="worker/index" class="form-control selectpage" name="row[worker_id]" type="text" value="{$row.worker_id|htmlentities}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Remark')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-remark" data-rule="required" class="form-control" name="row[remark]" type="text" value="{$row.remark|htmlentities}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Need_notice')}:</label>
<div class="col-xs-12 col-sm-8">
<select id="c-need_notice" data-rule="required" class="form-control selectpicker" name="row[need_notice]">
{foreach name="needNoticeList" item="vo"}
<option value="{$key}" {in name="key" value="$row.need_notice"}selected{/in}>{$vo}</option>
{/foreach}
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
<div class="col-xs-12 col-sm-8">
<div class="radio">
{foreach name="statusList" item="vo"}
<label for="row[status]-{$key}"><input id="row[status]-{$key}" name="row[status]" type="radio" value="{$key}" {in name="key" value="$row.status"}checked{/in} /> {$vo}</label>
{/foreach}
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Notice_time')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-notice_time" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-use-current="true" name="row[notice_time]" type="text" value="{$row.notice_time}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Create_time')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-create_time" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-use-current="true" name="row[create_time]" type="text" value="{$row.create_time}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Update_time')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-update_time" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-use-current="true" name="row[update_time]" type="text" value="{$row.update_time}">
</div>
</div>
<div class="form-group layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
</div>
</div>
</form>

View File

@ -0,0 +1,46 @@
<div class="panel panel-default panel-intro">
<div class="panel-heading">
{:build_heading(null,FALSE)}
<ul class="nav nav-tabs" data-field="status">
<li class="{:$Think.get.status === null ? 'active' : ''}"><a href="#t-all" data-value="" data-toggle="tab">{:__('All')}</a></li>
{foreach name="statusList" item="vo"}
<li class="{:$Think.get.status === (string)$key ? 'active' : ''}"><a href="#t-{$key}" data-value="{$key}" data-toggle="tab">{$vo}</a></li>
{/foreach}
</ul>
</div>
<div class="panel-body">
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade active in" id="one">
<div class="widget-body no-padding">
<div id="toolbar" class="toolbar">
<a href="javascript:;" class="btn btn-primary btn-refresh" title="{:__('Refresh')}" ><i class="fa fa-refresh"></i> </a>
<a href="javascript:;" class="btn btn-success btn-add {:$auth->check('orders/dispatchrecord/add')?'':'hide'}" title="{:__('Add')}" ><i class="fa fa-plus"></i> {:__('Add')}</a>
<a href="javascript:;" class="btn btn-success btn-edit btn-disabled disabled {:$auth->check('orders/dispatchrecord/edit')?'':'hide'}" title="{:__('Edit')}" ><i class="fa fa-pencil"></i> {:__('Edit')}</a>
<a href="javascript:;" class="btn btn-danger btn-del btn-disabled disabled {:$auth->check('orders/dispatchrecord/del')?'':'hide'}" title="{:__('Delete')}" ><i class="fa fa-trash"></i> {:__('Delete')}</a>
<div class="dropdown btn-group {:$auth->check('orders/dispatchrecord/multi')?'':'hide'}">
<a class="btn btn-primary btn-more dropdown-toggle btn-disabled disabled" data-toggle="dropdown"><i class="fa fa-cog"></i> {:__('More')}</a>
<ul class="dropdown-menu text-left" role="menu">
{foreach name="statusList" item="vo"}
<li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:" data-params="status={$key}">{:__('Set status to ' . $key)}</a></li>
{/foreach}
</ul>
</div>
</div>
<table id="table" class="table table-striped table-bordered table-hover table-nowrap"
data-operate-edit="{:$auth->check('orders/dispatchrecord/edit')}"
data-operate-del="{:$auth->check('orders/dispatchrecord/del')}"
width="100%">
</table>
</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,46 @@
<?php
namespace app\common\Logic;
use app\common\services\alibaba\DyvmsService;
use think\Exception;
/**
* 通知
*/
class NoticeLogic
{
public function __construct($types = [])
{
}
/**
* 派单通知
* @return void
*/
public function dispatchNotice($dispatch,$type)
{
$ttsCode = '';
$outId = '';
try {
$reponse = DyvmsService::getInstance()->call($dispatch->worker_tel, $ttsCode, $outId);
}catch (Exception $exception){
dump($exception->getMessage());
}
}
/**
* 超时通知
* @return void
*/
public function overTimeNotice(){
}
}

View File

@ -2,8 +2,11 @@
namespace app\common\Logic;
use app\admin\controller\orders\Dispatch;
use app\admin\model\Order;
use app\admin\model\OrderDispatch;
use fast\Auth;
use think\Db;
use think\db\exception\DataNotFoundException;
use think\db\exception\ModelNotFoundException;
use think\Exception;
@ -57,6 +60,84 @@ class OrderLogic
$params['remark'] = $roleInfo['remark'] ?? $orderDispatch->remark;
Hook::listen('order_change', $params);
$hookParams = [
'dispatch' => $orderDispatch,
'remark' => $roleInfo['remark'] ?? $orderDispatch->remark,
];
Hook::listen('order_dispatch_change', $hookParams);
}
/**
*
* 师傅超时未接单的处理逻辑
* @return void
*/
public function noWorkerCanGetIt(OrderDispatch $dispatch)
{
$maxNoticeNum = 3;
if($dispatch->notice > $maxNoticeNum){ //超过三次,直接取消
Db::startTrans();
try {
$dispatch->notice_num ++;
$dispatch->notice_time = date('Y-m-d H:i:s');
$remark = '师傅超时未接单,任务取消';
$this->cancelOrderDispatch($dispatch,null,$remark);
Db::commit();
}catch (Exception $exception){
Db::rollback();
$remark = '任务取消异常,请联系技术人员:'.$exception->getMessage();
$dispatch->notice_num ++;
$dispatch->remark = $remark;
$dispatch->notice_time = date('Y-m-d H:i:s');
$dispatch->save();
}
}else{ //未超过最大值,则通知短信通知
$dispatch->notice_num ++;
$dispatch->notice_time = date('Y-m-d H:i:s');
$dispatch->save();
//发送短信通知师傅 todo...
$smsLogic = new NoticeLogic();
}
}
/**
* 取消任务
* @param Dispatch $dispatch
* @return void
*/
public function cancelOrderDispatch(OrderDispatch $dispatch,$auth=null,$remark='')
{
$order = Order::where('id',$dispatch->id)->where('status',Order::STATUS_DISPATCHED)->find();
if(!empty($order)){
throw new Exception('未找到关联订单');
}
//取消
$dispatch->allowField(true)->save(['status' => OrderDispatch::STATUS_CANCEL, 'remark' => $remark]);
//回退订单状态
$order->allowField(true)->save(['status' => Order::STATUS_DISPATCHING]);
$params['order'] = $order;
$params['role'] = 1;
$params['auth'] = $auth;
$params['remark'] = '任务被取消[ID' . $dispatch->id . '],订单状态回退';
if (!empty($remark)) {
$params['remark'] .= ',备注:' . $remark;
}
Hook::listen('order_change', $params);
$hookParams = [
'dispatch' => $dispatch,
'remark' => '后台取消,admin:'.$auth->nickname??0,
];
Hook::listen('order_dispatch_change', $hookParams);
}
}

View File

@ -0,0 +1,40 @@
<?php
namespace app\common\command;
use app\admin\model\OrderDispatch;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\Hook;
class CheckOrderDispatchCommand extends Command
{
protected function configure()
{
$this->setName('check:dispatch-overtime')
->setDescription('检测dispatch表超时任务每分钟检测一次');
}
protected function execute(Input $input, Output $output){
$Model = new OrderDispatch();
$now = date('Y-m-d H:i:s');
$Model->where('status',OrderDispatch::STATUS_PLANIT)
->where('plan_time','<=',$now)
->chunk(100, function ($list) {
foreach ($list as $item) {
//1修改为超时
$item->status = OrderDispatch::STATUS_OVERTIME;
$item->save();
$params = ['dispatch'=>$item,'remark'=>'系统自动处理,任务超时'];
Hook::listen('order_dispatch_change',$params);
}
});
}
}

View File

@ -0,0 +1,42 @@
<?php
namespace app\common\command;
use app\admin\model\Order;
use app\admin\model\OrderDispatch;
use app\common\Logic\OrderLogic;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\Hook;
class CheckOrderDispatchGotCommand extends Command
{
protected function configure()
{
$this->setName('check:dispatch-toget')
->setDescription('dispatch未接单通知,每五分钟检测一次');
}
protected function execute(Input $input, Output $output){
$Model = new OrderDispatch();
$now = date('Y-m-d H:i:s',time()-30*60); //创建三十分名以上未接的任务
$now2 = date('Y-m-d H:i:s',time()-30*600); //上次通知在30分钟以前
$OrderLogic = new OrderLogic();
$Model->where('status',OrderDispatch::STATUS_TOGET)
->where('create_time','<=',$now)
->where('notice_time','<=',$now2)
->chunk(100, function ($list) use ($OrderLogic){
foreach ($list as $item) {
$OrderLogic->noWorkerCanGetIt($item);
}
});
}
}

View File

@ -0,0 +1,58 @@
<?php
namespace app\common\services\alibaba;
use AlibabaCloud\SDK\Dyvmsapi\V20170525\Dyvmsapi;
use AlibabaCloud\SDK\Dyvmsapi\V20170525\Models\SingleCallByTtsRequest;
use Darabonba\OpenApi\Models\Config;
use think\Env;
class DyvmsService
{
// 保存实例的静态变量
protected static ?DyvmsService $instance = null;
protected Dyvmsapi $service;
// 私有构造函数,防止外部直接实例化
private function __construct($options = [])
{
$config = Env::get('alibaba_dyvms');
if (!empty($options)) {
$config = array_merge($config, $options);
}
$this->service = new Dyvmsapi(new Config($config));
}
// 单例方法,确保只有一个实例
public static function getInstance($options = []): ?DyvmsService
{
if (self::$instance === null) {
self::$instance = new self($options); // 创建实例
}
return self::$instance; // 返回实例
}
// 防止克隆实例
private function __clone()
{
}
// 防止反序列化
private function __wakeup()
{
}
// 调用阿里云接口发送语音
public function call($tel,$ttsCode,$outId): array|\AlibabaCloud\SDK\Dyvmsapi\V20170525\Models\SingleCallByTtsResponse
{
$request = new SingleCallByTtsRequest([
'calledNumber' => $tel,
'calledShowNumber' => '',//显示专属号码
'ttsCode' => $ttsCode,// 语音文件ID
'outId' => $outId, //外部ID
// 其他必要参数可以继续添加
]);
return $this->service->singleCallByTts($request);
}
}

View File

@ -173,7 +173,7 @@ return [
// 日志保存目录
'path' => LOG_PATH,
// 日志记录级别
'level' => [],
'level' => ['log','error'],
],
// +----------------------------------------------------------------------
// | Trace设置 开启 app_trace 后 有效

View File

@ -0,0 +1,12 @@
<?php
return [
'accessKeyId' => '',
'accessKeySecret' => '',
'regionId' => '', //可用区ID
'calledShowNumber' => '', //专属号码
];

View File

@ -98,7 +98,7 @@ return [
'Home' => '首页',
'Store' => '插件市场',
'Wxapp' => '小程序',
'Services' => '服务',
'Services' => '服务类目',
'Download' => '下载',
'Demo' => '演示',
'Donation' => '捐赠',

View File

@ -43,4 +43,9 @@ return [
'app\\admin\\behavior\\OrderLog',
'app\\admin\\behavior\\OrderChangeAfter',
],
'order_dispatch_change' => [
'app\\admin\\behavior\\OrderDispatchLog',
'app\\admin\\behavior\\SendOverTimeSms',
],
];

View File

@ -31,6 +31,8 @@
"ext-bcmath": "*",
"txthinking/mailer": "^2.0",
"symfony/var-dumper": "^6.4",
"alibabacloud/dyvmsapi-20170525": "^3.2"
"symfony/var-dumper": "^6.4",
"nesbot/carbon": "^3.8"
},
"config": {

619
composer.lock generated
View File

@ -5,6 +5,7 @@
"This file is @generated automatically"
],
"content-hash": "e7a7644d2fa0b40802cdaf3d19eba0eb",
"content-hash": "770cae8dc7a1ad5a354ecc3345632f98",
"packages": [
{
"name": "carbonphp/carbon-doctrine-types",
@ -81,6 +82,564 @@
],
"time": "2024-02-09T16:56:22+00:00"
},
{
"name": "adbario/php-dot-notation",
"version": "2.5.0",
"source": {
"type": "git",
"url": "https://github.com/adbario/php-dot-notation.git",
"reference": "081e2cca50c84bfeeea2e3ef9b2c8d206d80ccae"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/adbario/php-dot-notation/zipball/081e2cca50c84bfeeea2e3ef9b2c8d206d80ccae",
"reference": "081e2cca50c84bfeeea2e3ef9b2c8d206d80ccae",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"ext-json": "*",
"php": "^5.5 || ^7.0 || ^8.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8|^5.7|^6.6|^7.5|^8.5|^9.5",
"squizlabs/php_codesniffer": "^3.6"
},
"type": "library",
"autoload": {
"files": [
"src/helpers.php"
],
"psr-4": {
"Adbar\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Riku Särkinen",
"email": "riku@adbar.io"
}
],
"description": "PHP dot notation access to arrays",
"homepage": "https://github.com/adbario/php-dot-notation",
"keywords": [
"ArrayAccess",
"dotnotation"
],
"support": {
"issues": "https://github.com/adbario/php-dot-notation/issues",
"source": "https://github.com/adbario/php-dot-notation/tree/2.5.0"
},
"time": "2022-10-14T20:31:46+00:00"
},
{
"name": "alibabacloud/credentials",
"version": "1.2.1",
"source": {
"type": "git",
"url": "https://github.com/aliyun/credentials-php.git",
"reference": "cd0f65127d010ce3be5ced13fa9b69218dcfc555"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/aliyun/credentials-php/zipball/cd0f65127d010ce3be5ced13fa9b69218dcfc555",
"reference": "cd0f65127d010ce3be5ced13fa9b69218dcfc555",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"adbario/php-dot-notation": "^2.2",
"alibabacloud/tea": "^3.0",
"ext-curl": "*",
"ext-json": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-openssl": "*",
"ext-simplexml": "*",
"ext-xmlwriter": "*",
"guzzlehttp/guzzle": "^6.3|^7.0",
"php": ">=5.6"
},
"require-dev": {
"composer/composer": "^1.8",
"drupal/coder": "^8.3",
"ext-dom": "*",
"ext-pcre": "*",
"ext-sockets": "*",
"ext-spl": "*",
"mikey179/vfsstream": "^1.6",
"monolog/monolog": "^1.24",
"phpunit/phpunit": "^5.7|^6.6|^9.3",
"psr/cache": "^1.0",
"symfony/dotenv": "^3.4",
"symfony/var-dumper": "^3.4"
},
"suggest": {
"ext-sockets": "To use client-side monitoring"
},
"type": "library",
"autoload": {
"psr-4": {
"AlibabaCloud\\Credentials\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "Alibaba Cloud SDK",
"email": "sdk-team@alibabacloud.com",
"homepage": "http://www.alibabacloud.com"
}
],
"description": "Alibaba Cloud Credentials for PHP",
"homepage": "https://www.alibabacloud.com/",
"keywords": [
"alibaba",
"alibabacloud",
"aliyun",
"client",
"cloud",
"credentials",
"library",
"sdk",
"tool"
],
"support": {
"issues": "https://github.com/aliyun/credentials-php/issues",
"source": "https://github.com/aliyun/credentials-php"
},
"time": "2025-03-03T12:51:01+00:00"
},
{
"name": "alibabacloud/darabonba-openapi",
"version": "0.2.13",
"source": {
"type": "git",
"url": "https://github.com/alibabacloud-sdk-php/darabonba-openapi.git",
"reference": "0213396384e2c064eefd614f3dd53636a63f987f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/alibabacloud-sdk-php/darabonba-openapi/zipball/0213396384e2c064eefd614f3dd53636a63f987f",
"reference": "0213396384e2c064eefd614f3dd53636a63f987f",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"alibabacloud/credentials": "^1.1",
"alibabacloud/gateway-spi": "^1",
"alibabacloud/openapi-util": "^0.1.10|^0.2.1",
"alibabacloud/tea-utils": "^0.2.21",
"alibabacloud/tea-xml": "^0.2",
"php": ">5.5"
},
"type": "library",
"autoload": {
"psr-4": {
"Darabonba\\OpenApi\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "Alibaba Cloud SDK",
"email": "sdk-team@alibabacloud.com"
}
],
"description": "Alibaba Cloud OpenApi Client",
"support": {
"issues": "https://github.com/alibabacloud-sdk-php/darabonba-openapi/issues",
"source": "https://github.com/alibabacloud-sdk-php/darabonba-openapi/tree/0.2.13"
},
"time": "2024-07-15T13:11:36+00:00"
},
{
"name": "alibabacloud/dyvmsapi-20170525",
"version": "3.2.2",
"source": {
"type": "git",
"url": "https://github.com/alibabacloud-sdk-php/Dyvmsapi-20170525.git",
"reference": "20c50b61eb383d1aebbdcfe91fa3808fc81fad3a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/alibabacloud-sdk-php/Dyvmsapi-20170525/zipball/20c50b61eb383d1aebbdcfe91fa3808fc81fad3a",
"reference": "20c50b61eb383d1aebbdcfe91fa3808fc81fad3a",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"alibabacloud/darabonba-openapi": "^0.2.13",
"alibabacloud/endpoint-util": "^0.1.0",
"alibabacloud/openapi-util": "^0.1.10|^0.2.1",
"alibabacloud/tea-utils": "^0.2.21",
"php": ">5.5"
},
"type": "library",
"autoload": {
"psr-4": {
"AlibabaCloud\\SDK\\Dyvmsapi\\V20170525\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "Alibaba Cloud SDK",
"email": "sdk-team@alibabacloud.com"
}
],
"description": "Alibaba Cloud Dyvmsapi (20170525) SDK Library for PHP",
"support": {
"source": "https://github.com/alibabacloud-sdk-php/Dyvmsapi-20170525/tree/3.2.2"
},
"time": "2024-10-15T09:56:52+00:00"
},
{
"name": "alibabacloud/endpoint-util",
"version": "0.1.1",
"source": {
"type": "git",
"url": "https://github.com/alibabacloud-sdk-php/endpoint-util.git",
"reference": "f3fe88a25d8df4faa3b0ae14ff202a9cc094e6c5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/alibabacloud-sdk-php/endpoint-util/zipball/f3fe88a25d8df4faa3b0ae14ff202a9cc094e6c5",
"reference": "f3fe88a25d8df4faa3b0ae14ff202a9cc094e6c5",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">5.5"
},
"require-dev": {
"phpunit/phpunit": "^4.8.35|^5.4.3"
},
"type": "library",
"autoload": {
"psr-4": {
"AlibabaCloud\\Endpoint\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "Alibaba Cloud SDK",
"email": "sdk-team@alibabacloud.com"
}
],
"description": "Alibaba Cloud Endpoint Library for PHP",
"support": {
"source": "https://github.com/alibabacloud-sdk-php/endpoint-util/tree/0.1.1"
},
"time": "2020-06-04T10:57:15+00:00"
},
{
"name": "alibabacloud/gateway-spi",
"version": "1.0.0",
"source": {
"type": "git",
"url": "https://github.com/alibabacloud-sdk-php/alibabacloud-gateway-spi.git",
"reference": "7440f77750c329d8ab252db1d1d967314ccd1fcb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/alibabacloud-sdk-php/alibabacloud-gateway-spi/zipball/7440f77750c329d8ab252db1d1d967314ccd1fcb",
"reference": "7440f77750c329d8ab252db1d1d967314ccd1fcb",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"alibabacloud/credentials": "^1.1",
"php": ">5.5"
},
"type": "library",
"autoload": {
"psr-4": {
"Darabonba\\GatewaySpi\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "Alibaba Cloud SDK",
"email": "sdk-team@alibabacloud.com"
}
],
"description": "Alibaba Cloud Gateway SPI Client",
"support": {
"source": "https://github.com/alibabacloud-sdk-php/alibabacloud-gateway-spi/tree/1.0.0"
},
"time": "2022-07-14T05:31:35+00:00"
},
{
"name": "alibabacloud/openapi-util",
"version": "0.2.1",
"source": {
"type": "git",
"url": "https://github.com/alibabacloud-sdk-php/openapi-util.git",
"reference": "f31f7bcd835e08ca24b6b8ba33637eb4eceb093a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/alibabacloud-sdk-php/openapi-util/zipball/f31f7bcd835e08ca24b6b8ba33637eb4eceb093a",
"reference": "f31f7bcd835e08ca24b6b8ba33637eb4eceb093a",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"alibabacloud/tea": "^3.1",
"alibabacloud/tea-utils": "^0.2",
"lizhichao/one-sm": "^1.5",
"php": ">5.5"
},
"require-dev": {
"phpunit/phpunit": "*"
},
"type": "library",
"autoload": {
"psr-4": {
"AlibabaCloud\\OpenApiUtil\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "Alibaba Cloud SDK",
"email": "sdk-team@alibabacloud.com"
}
],
"description": "Alibaba Cloud OpenApi Util",
"support": {
"issues": "https://github.com/alibabacloud-sdk-php/openapi-util/issues",
"source": "https://github.com/alibabacloud-sdk-php/openapi-util/tree/0.2.1"
},
"time": "2023-01-10T09:10:10+00:00"
},
{
"name": "alibabacloud/tea",
"version": "3.2.1",
"source": {
"type": "git",
"url": "https://github.com/aliyun/tea-php.git",
"reference": "1619cb96c158384f72b873e1f85de8b299c9c367"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/aliyun/tea-php/zipball/1619cb96c158384f72b873e1f85de8b299c9c367",
"reference": "1619cb96c158384f72b873e1f85de8b299c9c367",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"adbario/php-dot-notation": "^2.4",
"ext-curl": "*",
"ext-json": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-openssl": "*",
"ext-simplexml": "*",
"ext-xmlwriter": "*",
"guzzlehttp/guzzle": "^6.3|^7.0",
"php": ">=5.5"
},
"require-dev": {
"phpunit/phpunit": "*",
"symfony/dotenv": "^3.4",
"symfony/var-dumper": "^3.4"
},
"suggest": {
"ext-sockets": "To use client-side monitoring"
},
"type": "library",
"autoload": {
"psr-4": {
"AlibabaCloud\\Tea\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "Alibaba Cloud SDK",
"email": "sdk-team@alibabacloud.com",
"homepage": "http://www.alibabacloud.com"
}
],
"description": "Client of Tea for PHP",
"homepage": "https://www.alibabacloud.com/",
"keywords": [
"alibabacloud",
"client",
"cloud",
"tea"
],
"support": {
"issues": "https://github.com/aliyun/tea-php/issues",
"source": "https://github.com/aliyun/tea-php"
},
"time": "2023-05-16T06:43:41+00:00"
},
{
"name": "alibabacloud/tea-utils",
"version": "0.2.21",
"source": {
"type": "git",
"url": "https://github.com/alibabacloud-sdk-php/tea-utils.git",
"reference": "5039e45714c6456186d267f5d81a4b260a652495"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/alibabacloud-sdk-php/tea-utils/zipball/5039e45714c6456186d267f5d81a4b260a652495",
"reference": "5039e45714c6456186d267f5d81a4b260a652495",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"alibabacloud/tea": "^3.1",
"php": ">5.5"
},
"type": "library",
"autoload": {
"psr-4": {
"AlibabaCloud\\Tea\\Utils\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "Alibaba Cloud SDK",
"email": "sdk-team@alibabacloud.com"
}
],
"description": "Alibaba Cloud Tea Utils for PHP",
"support": {
"issues": "https://github.com/aliyun/tea-util/issues",
"source": "https://github.com/aliyun/tea-util"
},
"time": "2024-07-05T06:05:54+00:00"
},
{
"name": "alibabacloud/tea-xml",
"version": "0.2.4",
"source": {
"type": "git",
"url": "https://github.com/alibabacloud-sdk-php/tea-xml.git",
"reference": "3e0c000bf536224eebbac913c371bef174c0a16a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/alibabacloud-sdk-php/tea-xml/zipball/3e0c000bf536224eebbac913c371bef174c0a16a",
"reference": "3e0c000bf536224eebbac913c371bef174c0a16a",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">5.5"
},
"require-dev": {
"phpunit/phpunit": "*",
"symfony/var-dumper": "*"
},
"type": "library",
"autoload": {
"psr-4": {
"AlibabaCloud\\Tea\\XML\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "Alibaba Cloud SDK",
"email": "sdk-team@alibabacloud.com"
}
],
"description": "Alibaba Cloud Tea XML Library for PHP",
"support": {
"source": "https://github.com/alibabacloud-sdk-php/tea-xml/tree/0.2.4"
},
"time": "2022-08-02T04:12:58+00:00"
},
{
"name": "composer/pcre",
"version": "3.3.2",
@ -550,6 +1109,66 @@
},
"time": "2024-03-28T04:15:16+00:00"
},
{
"name": "lizhichao/one-sm",
"version": "1.10",
"source": {
"type": "git",
"url": "https://github.com/lizhichao/sm.git",
"reference": "687a012a44a5bfd4d9143a0234e1060543be455a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/lizhichao/sm/zipball/687a012a44a5bfd4d9143a0234e1060543be455a",
"reference": "687a012a44a5bfd4d9143a0234e1060543be455a",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=5.6"
},
"type": "library",
"autoload": {
"psr-4": {
"OneSm\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "tanszhe",
"email": "1018595261@qq.com"
}
],
"description": "国密sm3",
"keywords": [
"php",
"sm3"
],
"support": {
"issues": "https://github.com/lizhichao/sm/issues",
"source": "https://github.com/lizhichao/sm/tree/1.10"
},
"funding": [
{
"url": "https://www.vicsdf.com/img/w.jpg",
"type": "custom"
},
{
"url": "https://www.vicsdf.com/img/z.jpg",
"type": "custom"
}
],
"time": "2021-05-26T06:19:22+00:00"
},
{
"name": "maennchen/zipstream-php",
"version": "3.1.1",

View File

@ -24,7 +24,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
Form.events.selectpage(form);
});
$.fn.bootstrapTable.locales[Table.defaults.locale]['formatSearch'] = function(){return "订单号/客户电话/客户姓名";};
$.fn.bootstrapTable.locales[Table.defaults.locale]['formatSearch'] = function(){return "订单号/客户电话/客户姓名";};
// 初始化表格
table.bootstrapTable({
@ -56,17 +56,17 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
{field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate,
formatter: Table.api.formatter.operate,
buttons:[
{
name:"detail",
text:"",
title:"详情",
classname:"btn btn-xs btn-info btn-view btn-dialog",
icon:'fa fa-eye',
url: 'orders/abnormal/edit/'
}
]
// buttons:[
// {
// name:"detail",
// text:"",
// title:"详情",
// classname:"btn btn-xs btn-info btn-view btn-dialog",
// icon:'fa fa-eye',
// url: 'orders/abnormal/edit/'
//
// }
// ]
}
]
]

View File

@ -48,7 +48,9 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
// {field: 'plan_time', title: __('Plan_time'), operate:'RANGE', addclass:'datetimerange', autocomplete:false},
{field: 'admin_id', title: __('Admin_id')},
{field: 'online_amount', title: __('Online_amount'), operate:false},
{field: 'online_amount_last', title: __('Online_amount_last'), operate:false},
{field: 'offline_amount', title: __('Offline_amount'), operate:false},
{field: 'offline_amount_type_text', title: __('Offline_amount_type'), operate:false},
{field: 'total', title: __('Total'), operate:'BETWEEN'},
{field: 'discount_amount', title: __('Discount_amount'), operate:false},
{field: 'real_amount', title: __('Real_amount'), operate:false},

View File

@ -43,11 +43,19 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
{field: 'source_shop', title: __('Source_shop'), operate: 'LIKE'},
// {field: 'source', title: __('Source')},
// {field: 'source_uid', title: __('Source_uid'), operate: 'LIKE'},
{field: 'item_title', title: __('Item_title'), operate: 'LIKE'},
{field: 'item_title', title: __('Item_title'), operate: false},
{field: 'total', title: __('Total'), operate:'BETWEEN'},
{field: 'online_amount', title: __('Online_amount'), operate:'BETWEEN'},
{field: 'offline_amount', title: __('Offline_amount'), operate:'BETWEEN'},
{field: 'online_amount', title: __('Online_amount'), operate:false},
{field: 'online_amount_last', title: __('Online_amount_last'), operate:false},
{field: 'offline_amount', title: __('Offline_amount'), operate:false},
{field: 'offline_amount_type_text', title: __('Offline_amount_type'), operate:false},
{field: 'refund_amount', title: __('Refund_amount'), operate:false},
{field: 'real_amount', title: __('Real_amount'), operate:false},
{field: 'cost', title: __('Cost'), operate:false},
{field: 'performance', title: __('Performance'), operate:false},
// {field: 'dispatch_type', title: __('Dispatch_type')},
{field: 'create_time', title: __('Create_time'), operate:'RANGE', addclass:'datetimerange', autocomplete:false},

View File

@ -43,19 +43,31 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form','layer'], function ($,
{field: 'order.order_no', title: __('Order.order_no'), operate: 'LIKE'},
{field: 'status', title: __('Status'), searchList: {"0":__('Status 0'),"10":__('Status 10'),"20":__('Status 20'),"25":__('Status 25'),"30":__('Status 30'),"60":__('Status 60'),"-10":__('Status -10'),"-20":__('Status -20'),"-30":__('Status -30')}, formatter: Table.api.formatter.status},
// {field: 'worker_id', title: __('Worker_id')},
{field: 'worker_name', title: __('Worker_name'), operate: 'LIKE'},
{field: 'worker_tel', title: __('Worker_tel'), operate: 'LIKE'},
{field: 'type', title: __('Type'), searchList: {"1":__('Type 1')}, formatter: Table.api.formatter.normal},
{field: 'plan_time', title: __('Plan_time'), operate:'RANGE', addclass:'datetimerange', autocomplete:false},
{field: 'status', title: __('Status'), searchList: {"0":__('Status 0'),"10":__('Status 10'),"20":__('Status 20'),"25":__('Status 25'),"30":__('Status 30'),"60":__('Status 60'),"-10":__('Status -10'),
//"-20":__('Status -20'),
"-30":__('Status -30')},
formatter: Table.api.formatter.status,
custom:{25:"red"}
},
{field: 'plan_time', title: __('Plan_time'), operate:'RANGE', addclass:'datetimerange', autocomplete:false,
formatter:function(value,row,index){
if(row.status == 25){
return' <span style="color:red;font-weight: bold">'+value+'</span>';
}else{
return value;
}
}},
{field: 'order.source_shop', title: __('Order.source_shop'), operate: 'LIKE'},
{field: 'order.source', title: __('Order.source')},
// {field: 'order.source', title: __('Order.source')},
{field: 'order.customer', title: __('Order.customer'), operate: 'LIKE'},
{field: 'order.tel', title: __('Order.tel'), operate: 'LIKE'},
{field: 'order.address', title: __('Order.address'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content},
@ -68,11 +80,11 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form','layer'], function ($,
{field: 'remark', title: __('Remark'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content},
// {field: 'is_notice', title: __('Is_notice'), searchList: {"0":__('Is_notice 0'),"1":__('Is_notice 1')}, formatter: Table.api.formatter.normal},
{field: 'finish_time', title: __('Finish_time'), operate:'RANGE', addclass:'datetimerange', autocomplete:false},
// {field: 'admin_id', title: __('Admin_id')},
{field: 'admin_user', title: __('Admin_user'), operate: 'LIKE'},
{field: 'create_time', title: __('Create_time'), operate:'RANGE', addclass:'datetimerange', autocomplete:false},
{field: 'update_time', title: __('Update_time'), operate:'RANGE', addclass:'datetimerange', autocomplete:false},
{field: 'finish_time', title: __('Finish_time'), operate:'RANGE', addclass:'datetimerange', autocomplete:false},
{field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate,
@ -99,7 +111,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form','layer'], function ($,
text:"完成",
title:"完成",
icon: 'fa fa-check',
url: 'orders/dispatch2/finish',
url:'orders/dispatch2/finish',
extend: 'data-toggle="tooltip" data-container="body"',
classname: 'btn btn-xs btn-success btn-dialog',
visible:function(row){
@ -109,6 +121,21 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form','layer'], function ($,
return false;
}
},
{
name: 'addrecord',
text:"备忘",
title:"备忘",
icon: 'fa fa-list',
url: 'orders/dispatchrecord/add',
extend: 'data-toggle="tooltip" data-container="body"',
classname: 'btn btn-xs btn-warning btn-dialog',
visible:function(row){
if(row.btn_record){
return true;
}
return false;
}
},
],
}
@ -216,6 +243,9 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form','layer'], function ($,
finish: function () {
Controller.api.bindevent();
},
addrecord: function () {
Controller.api.bindevent();
},
api: {
bindevent: function () {
Form.api.bindevent($("form[role=form]"));

View File

@ -0,0 +1,61 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: function () {
// 初始化表格参数配置
Table.api.init({
extend: {
index_url: 'orders/dispatchrecord/index' + location.search,
// add_url: 'orders/dispatchrecord/add',
edit_url: 'orders/dispatchrecord/edit',
del_url: 'orders/dispatchrecord/del',
multi_url: 'orders/dispatchrecord/multi',
import_url: 'orders/dispatchrecord/import',
table: 'order_dispatch_record',
}
});
var table = $("#table");
// 初始化表格
table.bootstrapTable({
url: $.fn.bootstrapTable.defaults.extend.index_url,
pk: 'id',
sortName: 'id',
fixedColumns: true,
fixedRightNumber: 1,
columns: [
[
{checkbox: true},
{field: 'id', title: __('Id')},
{field: 'dispatch_id', title: __('Dispatch_id')},
{field: 'worker_id', title: __('Worker_id')},
{field: 'remark', title: __('Remark'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content},
{field: 'need_notice', title: __('Need_notice'), searchList: {"0":__('Need_notice 0'),"1":__('Need_notice 1')}, formatter: Table.api.formatter.normal},
{field: 'status', title: __('Status'), searchList: {"0":__('Status 0'),"1":__('Status 1')}, formatter: Table.api.formatter.status},
{field: 'notice_time', title: __('Notice_time'), operate:'RANGE', addclass:'datetimerange', autocomplete:false},
{field: 'create_time', title: __('Create_time'), operate:'RANGE', addclass:'datetimerange', autocomplete:false},
{field: 'update_time', title: __('Update_time'), operate:'RANGE', addclass:'datetimerange', autocomplete:false},
{field: 'admin_id', title: __('Admin_id')},
{field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate}
]
]
});
// 为表格绑定事件
Table.api.bindevent(table);
},
add: function () {
Controller.api.bindevent();
},
edit: function () {
Controller.api.bindevent();
},
api: {
bindevent: function () {
Form.api.bindevent($("form[role=form]"));
}
}
};
return Controller;
});

View File

@ -8,7 +8,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
index_url: 'orders/revisitorder/index' + location.search,
add_url: 'orders/revisitorder/add',
edit_url: 'orders/revisitorder/edit',
del_url: 'orders/revisitorder/del',
// del_url: 'orders/revisitorder/del',
multi_url: 'orders/revisitorder/multi',
import_url: 'orders/revisitorder/import',
table: 'order',
@ -26,7 +26,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
fixedRightNumber: 1,
columns: [
[
{checkbox: true},
// {checkbox: true},
{field: 'id', title: __('Id')},
{field: 'order_no', title: __('Order_no'), operate: 'LIKE'},
{field: 'customer', title: __('Customer'), operate: 'LIKE'},
@ -57,7 +57,26 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
{field: 'create_time', title: __('Create_time'), operate:'RANGE', addclass:'datetimerange', autocomplete:false},
{field: 'update_time', title: __('Update_time'), operate:'RANGE', addclass:'datetimerange', autocomplete:false},
{field: 'delete_time', title: __('Delete_time'), operate:'RANGE', addclass:'datetimerange', autocomplete:false},
{field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate}
{field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate,
align:'left',
buttons:[
{
name: 'edit',
text:"回访",
title:"回访",
icon: 'fa fa-pencil',
//title: __('Edit'),
extend: 'data-toggle="tooltip" data-container="body"',
classname: 'btn btn-xs btn-info btn-editone',
visible:function(row){
if(row.revisit_id <= 0){
return true;
}
return false;
}
},
]
}
]
]
});