Merge remote-tracking branch 'origin/feature/hant' into feature/hant
This commit is contained in:
commit
16864b967b
|
|
@ -194,4 +194,51 @@ if (!function_exists('build_heading')) {
|
|||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function getLocation($address){
|
||||
|
||||
|
||||
try {
|
||||
// 百度地图 API 的 URL 和 API Key
|
||||
$apiKey = config('map.baidu_app_key'); // 替换为您的 API Key
|
||||
|
||||
// 构建请求 URL
|
||||
$url = "http://api.map.baidu.com/geocoding/v3/?address=" . urlencode($address) . "&output=json&ak=" . $apiKey;
|
||||
|
||||
// 使用 cURL 请求接口
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
$response = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
// 解析返回的 JSON 数据
|
||||
$data = json_decode($response, true);
|
||||
|
||||
// 获取经纬度
|
||||
if ($data['status'] == 0) {
|
||||
$latitude = $data['result']['location']['lat']; // 纬度
|
||||
$longitude = $data['result']['location']['lng']; // 经度
|
||||
|
||||
|
||||
return [
|
||||
'lat' => $latitude,
|
||||
'lng' => $longitude,
|
||||
];
|
||||
} else {
|
||||
return [];
|
||||
//echo "地址解析失败: " . $data['msg'] . "\n";
|
||||
}
|
||||
|
||||
}catch (Exception $exception){
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -294,17 +294,17 @@ class Ajax extends Backend
|
|||
$province = $this->request->get('province');
|
||||
$city = $this->request->get('city');
|
||||
}
|
||||
$where = ['pid' => 0, 'level' => 1];
|
||||
$where = ['level' => 1];
|
||||
$provincelist = null;
|
||||
if ($province !== null) {
|
||||
$where['pid'] = $province;
|
||||
$where['code'] = ['like',$province."%"];
|
||||
$where['level'] = 2;
|
||||
if ($city !== null) {
|
||||
$where['pid'] = $city;
|
||||
$where['code'] = ['like',$city."%"];
|
||||
$where['level'] = 3;
|
||||
}
|
||||
}
|
||||
$provincelist = Db::name('area')->where($where)->field('id as value,name')->select();
|
||||
$provincelist = Db::name('areas')->where($where)->field('id as value,name')->select();
|
||||
$this->success('', '', $provincelist);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -390,6 +390,7 @@ class Order extends Backend
|
|||
$order->status = \app\admin\model\Order::STATUS_DISPATCHED;
|
||||
$order->dispatch_time = date('Y-m-d H:i:s');
|
||||
// $order->dispatch_admin_id = $this->auth->id;
|
||||
$order->worker_id = $worker_id;
|
||||
$order->save();
|
||||
|
||||
//日志
|
||||
|
|
|
|||
|
|
@ -54,17 +54,36 @@ class Aftersale extends Backend
|
|||
$this->relationSearch = true;
|
||||
//设置过滤方法
|
||||
$this->request->filter(['strip_tags', 'trim']);
|
||||
|
||||
if ($this->request->isAjax()) {
|
||||
|
||||
$from = $this->request->param('from',1);
|
||||
$man_id = $this->request->param('man_id');
|
||||
|
||||
//如果发送的来源是Selectpage,则转发到Selectpage
|
||||
if ($this->request->request('keyField')) {
|
||||
return $this->selectpage();
|
||||
}
|
||||
list($where, $sort, $order, $offset, $limit) = $this->buildparams();
|
||||
|
||||
$list = $this->model
|
||||
$builder = $this->model
|
||||
->with(['order'])
|
||||
->where($where)
|
||||
->order($sort, $order)
|
||||
->where($where);
|
||||
|
||||
if($from == 2){
|
||||
//$builder->where('refund_amount','>',0);
|
||||
//$builder->where('status','<>',-1);
|
||||
$builder->where('fa_aftersale.dispatch_admin_id',$man_id ?: 0);
|
||||
|
||||
}
|
||||
|
||||
if($from == 3){
|
||||
//$builder->where('refund_amount','>',0);
|
||||
//$builder->where('status','<>',-1);
|
||||
$builder->where('fa_aftersale.worker_id',$man_id ?: 0);
|
||||
}
|
||||
|
||||
$list = $builder->order($sort, $order)
|
||||
->paginate($limit);
|
||||
|
||||
foreach ($list as $row) {
|
||||
|
|
@ -148,6 +167,10 @@ class Aftersale extends Backend
|
|||
unset($params['company_refund_amount']);
|
||||
unset($params['worker_refund_amount']);
|
||||
}
|
||||
|
||||
$params['dispatch_admin_id'] = $order->dispatch_admin_id;
|
||||
$params['dispatch_admin_user'] = $order->dispatch_admin_user;
|
||||
|
||||
$result = $this->model->allowField(true)->save($params);
|
||||
$order->aftersale_id = $this->model->id;
|
||||
$order->save();
|
||||
|
|
|
|||
|
|
@ -155,6 +155,7 @@ class Dispatch extends Backend
|
|||
$order->status = Order::STATUS_DISPATCHED;
|
||||
$order->dispatch_time = date('Y-m-d H:i:s');
|
||||
$order->dispatch_admin_id = $this->auth->id;
|
||||
$order->worker_id = $worker->id;
|
||||
$order->save();
|
||||
|
||||
//order log
|
||||
|
|
|
|||
|
|
@ -19,14 +19,14 @@ class Dispatcher extends Backend
|
|||
|
||||
/**
|
||||
* Staorder模型对象
|
||||
* @var \app\admin\model\Order
|
||||
* @var Order
|
||||
*/
|
||||
protected $model = null;
|
||||
|
||||
public function _initialize()
|
||||
public function _initialize(): void
|
||||
{
|
||||
parent::_initialize();
|
||||
$this->model = new \app\admin\model\Order();
|
||||
$this->model = new Order();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -52,11 +52,14 @@ class Dispatcher extends Backend
|
|||
$today = now()->format('Y-m-d');
|
||||
$today_end = now()->format('Y-m-d');
|
||||
|
||||
|
||||
//设置过滤方法
|
||||
$this->request->filter(['strip_tags', 'trim']);
|
||||
if (false === $this->request->isAjax()) {
|
||||
$this->assign('daterange',$today.' - '.$today_end);
|
||||
|
||||
$this->assignconfig('default_daterange',now()->format('Y-m-d 00:00:00').' - '.now()->format('Y-m-d 23:59:59'));
|
||||
|
||||
return $this->view->fetch();
|
||||
}
|
||||
|
||||
|
|
@ -99,7 +102,7 @@ class Dispatcher extends Backend
|
|||
|
||||
|
||||
$newData = [
|
||||
['派单员','总业绩(¥)','转化率(%)','利润率(%)','变现值']
|
||||
['派单员','总业绩','转化率','利润率','变现值']
|
||||
];
|
||||
foreach ($data as $datum){
|
||||
$newData[] = [
|
||||
|
|
@ -114,10 +117,8 @@ class Dispatcher extends Backend
|
|||
}
|
||||
|
||||
//图表统计
|
||||
public function chart($filter,$getAll=false){
|
||||
|
||||
|
||||
|
||||
public function chart($filter,$getAll=false): \think\Collection|\think\Paginator|bool|array|string|\PDOStatement
|
||||
{
|
||||
|
||||
$orderValid = implode(',',$this->model->tabStatus(Order::TAB_VALID));
|
||||
|
||||
|
|
@ -127,7 +128,7 @@ class Dispatcher extends Backend
|
|||
"COUNT(CASE WHEN status = 60 THEN 1 END) AS finish_num", //完成数
|
||||
"COUNT(CASE WHEN status IN (".$orderValid.") THEN 1 END) AS count_num", //总订单数 (排除取消 和草稿)
|
||||
"SUM(CASE WHEN status = 60 THEN total END) AS total", //成效额
|
||||
"SUM(CASE WHEN status = 60 THEN total END) AS performance", //业绩
|
||||
"SUM(CASE WHEN status = 60 THEN performance END) AS performance", //业绩
|
||||
|
||||
"SUM(CASE WHEN status = 60 THEN (cost + material_cost) END) AS cost_total", //总成本
|
||||
|
||||
|
|
@ -164,7 +165,7 @@ class Dispatcher extends Backend
|
|||
}
|
||||
|
||||
if($getAll){
|
||||
$data = $builder->group('dispatch_admin_id')->select();
|
||||
$data = $builder->group('dispatch_admin_id')->limit(50)->select();
|
||||
}else{
|
||||
$data = $builder->group('dispatch_admin_id')->paginate();
|
||||
}
|
||||
|
|
@ -189,7 +190,7 @@ class Dispatcher extends Backend
|
|||
}else{
|
||||
$datum->admin_user = '系统';
|
||||
}
|
||||
$datum->avg_time_diff = $this->_calc($datum->avg_time_diff,3600,2);
|
||||
$datum->avg_time_diff = $this->_calc($datum->avg_time_diff,3600*24,2);
|
||||
|
||||
$datum->id = $datum->dispatch_admin_id;
|
||||
$newData[] = $datum->toArray();
|
||||
|
|
@ -208,10 +209,11 @@ class Dispatcher extends Backend
|
|||
/**
|
||||
* @param $a
|
||||
* @param $b
|
||||
* @param $scale
|
||||
* @param int $scale
|
||||
* @return int|string
|
||||
*/
|
||||
private function _calc($a,$b,$scale=4,$is_percent=false){
|
||||
private function _calc($a, $b, int $scale=4, $is_percent=false): int|string
|
||||
{
|
||||
$val = $b > 0 ? bcdiv($a,$b,$scale) : 0;
|
||||
|
||||
if($is_percent){
|
||||
|
|
|
|||
484
application/admin/controller/statistics/Worker.php
Normal file
484
application/admin/controller/statistics/Worker.php
Normal file
|
|
@ -0,0 +1,484 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller\statistics;
|
||||
|
||||
use app\admin\model\Admin;
|
||||
use app\admin\model\Aftersale;
|
||||
use app\admin\model\Order;
|
||||
use app\admin\model\OrderDispatch;
|
||||
use app\admin\model\OrderReview;
|
||||
use app\common\controller\Backend;
|
||||
use PDOStatement;
|
||||
use think\Collection;
|
||||
use think\Exception;
|
||||
use think\exception\DbException;
|
||||
use think\Loader;
|
||||
use think\response\Json;
|
||||
|
||||
/**
|
||||
* 师傅列管理
|
||||
*
|
||||
* @icon fa fa-circle-o
|
||||
*/
|
||||
class Worker extends Backend
|
||||
{
|
||||
|
||||
/**
|
||||
* Sworker模型对象
|
||||
* @var \app\admin\model\Worker
|
||||
*/
|
||||
protected $model = null;
|
||||
/**
|
||||
* @var Order
|
||||
*/
|
||||
private Order $OrderModel;
|
||||
/**
|
||||
* @var OrderDispatch
|
||||
*/
|
||||
private OrderDispatch $DispatchModel;
|
||||
|
||||
|
||||
protected $relationSearch = true;
|
||||
|
||||
public function _initialize()
|
||||
{
|
||||
parent::_initialize();
|
||||
$this->model = new \app\admin\model\Worker();
|
||||
$this->OrderModel = new Order();
|
||||
$this->DispatchModel = new OrderDispatch();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
|
||||
* 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
|
||||
* 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
|
||||
*/
|
||||
|
||||
/**
|
||||
* 查看
|
||||
*
|
||||
* @return string|Json
|
||||
* @throws Exception
|
||||
* @throws DbException
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
//设置过滤方法
|
||||
$this->request->filter(['strip_tags', 'trim']);
|
||||
if (false === $this->request->isAjax()) {
|
||||
$appkey = config('map.baidu_app_key');
|
||||
$this->assign('mapkey',$appkey);
|
||||
|
||||
$count = \app\admin\model\Worker::count();
|
||||
$active_count = \app\admin\model\Worker::where('location_update_time', '>=', date('Y-m-d H:i:s', strtotime('-30 days')))
|
||||
->count();
|
||||
|
||||
$add_count_1 = \app\admin\model\Worker::where('create_time', '>=', date('Y-m-d'))
|
||||
->count();
|
||||
|
||||
$active_count_7 = \app\admin\model\Worker::where('create_time', '>=', date('Y-m-d H:i:s', strtotime('-7 days')))
|
||||
->count();
|
||||
|
||||
$this->assign('count',$count);
|
||||
$this->assign('active_count',$active_count);
|
||||
$this->assign('add_count_1',$add_count_1);
|
||||
$this->assign('add_count_7',$active_count_7);
|
||||
|
||||
//待接单
|
||||
$todo_count = OrderDispatch::where('status',OrderDispatch::STATUS_TOGET)->count();
|
||||
//进行中
|
||||
$ing_count = OrderDispatch::whereIn('status',[OrderDispatch::STATUS_GOTIT,OrderDispatch::STATUS_PLANIT,OrderDispatch::STATUS_CLOCK])->count();
|
||||
//待验收
|
||||
$check_count = OrderDispatch::where('status',Order::STATUS_CHECKING)->count();
|
||||
//售后待处理
|
||||
$aftersale_count = Aftersale::where('status',1)->count();
|
||||
|
||||
$this->assign('todo_count',$todo_count);
|
||||
$this->assign('ing_count',$ing_count);
|
||||
$this->assign('check_count',$check_count);
|
||||
$this->assign('aftersale_count',$aftersale_count);
|
||||
|
||||
//师傅坐标
|
||||
$list = \app\admin\model\Worker::where('lng','>',0)->field(['lng','lat'])->select();
|
||||
$arr = [];
|
||||
foreach ($list as $item){
|
||||
$arr[] = [
|
||||
$item->lng, $item->lat,
|
||||
];
|
||||
}
|
||||
$this->assign('locationData',json_encode($arr));
|
||||
return $this->view->fetch();
|
||||
}
|
||||
//如果发送的来源是 Selectpage,则转发到 Selectpage
|
||||
if ($this->request->request('keyField')) {
|
||||
return $this->selectpage();
|
||||
}
|
||||
|
||||
$filter = $this->request->param('filter');
|
||||
$filter = json_decode($filter,true);
|
||||
if(!empty($filter['daterange'])){
|
||||
$arr = explode(' - ',$filter['daterange']);
|
||||
if(trim($arr[0])){
|
||||
$filter['start_time'] = trim($arr[0]);
|
||||
}
|
||||
if(trim($arr[1])){
|
||||
$filter['end_time'] = trim($arr[1]);
|
||||
}
|
||||
}
|
||||
|
||||
//派单表
|
||||
$dispatchSubsql = $this->dispatchSubsql($filter);
|
||||
//订单表
|
||||
$orderSubsql = $this->oderSubsql($filter);
|
||||
//评分表
|
||||
$viewSubsql = $this->viewSubsql($filter);
|
||||
|
||||
[$where, $sort, $order, $offset, $limit] = $this->buildparams();
|
||||
$list = $this->model->alias('fa_worker')
|
||||
->with(['area','items'])
|
||||
->field([
|
||||
'fa_worker.*',
|
||||
'IFNULL(a.dispatch_count, 0) AS dispatch_count',
|
||||
'IFNULL(a.get_count, 0) AS get_count',
|
||||
'IFNULL(a.refuse_count, 0) AS refuse_count',
|
||||
'IFNULL(a.arrive_count, 0) AS arrive_count',
|
||||
'IFNULL(a.avg_time_diff, 0) AS avg_time_diff',
|
||||
'IFNULL(b.finish_num, 0) AS finish_num',
|
||||
'IFNULL(b.total, 0) AS total',
|
||||
'IFNULL(b.performance, 0) AS performance',
|
||||
'IFNULL(b.refund_total, 0) AS refund_total',
|
||||
'IFNULL(b.refund_count, 0) AS refund_count',
|
||||
'IFNULL(b.cost, 0) AS cost',
|
||||
'IFNULL(c.good_count, 0) AS good_count'
|
||||
])
|
||||
->join([$dispatchSubsql => 'a'], 'fa_worker.id = a.worker_id', 'LEFT')
|
||||
->join([$orderSubsql => 'b'], 'fa_worker.id = b.worker_id', 'LEFT')
|
||||
->join([$viewSubsql => 'c'], 'fa_worker.id = c.worker_id', 'LEFT')
|
||||
->where($where)
|
||||
->order($sort, $order)
|
||||
->paginate($limit);
|
||||
|
||||
$this->_toList($list);
|
||||
$result = ['total' => $list->total(), 'rows' => $list->items()];
|
||||
return json($result);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return bool|Collection|PDOStatement|string
|
||||
* @throws DbException
|
||||
*/
|
||||
public function viewSubsql($filter=[]){
|
||||
//评分表
|
||||
$viewSubsql = OrderReview::where('worker_star',5)->field(['worker_id','count(*) as good_count']);
|
||||
|
||||
if(!empty($filter['start_time'])){
|
||||
$viewSubsql->where('create_time','>=',$filter['start_time']);
|
||||
}
|
||||
if(!empty($filter['end_time'])){
|
||||
$viewSubsql->where('create_time','<=',$filter['start_time']);
|
||||
}
|
||||
return $viewSubsql->group('worker_id')->buildSql();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|PDOStatement|string|Collection
|
||||
* @throws DbException
|
||||
*/
|
||||
public function dispatchSubsql($filter): Collection|bool|string|PDOStatement
|
||||
{
|
||||
$builder = new OrderDispatch();
|
||||
$fields = [
|
||||
'worker_id',
|
||||
"COUNT(*) AS dispatch_count", //分配数
|
||||
"COUNT(CASE WHEN status NOT IN (0, -10) THEN 1 END) AS get_count", //接单数
|
||||
//"COUNT(CASE WHEN status IN (60) THEN 1 END) AS finish_count", //完成数
|
||||
"COUNT(CASE WHEN status NOT IN (-10) THEN 1 END) AS refuse_count", //拒绝数
|
||||
"COUNT(arrive_time) AS arrive_count", //上门数
|
||||
"AVG(CASE WHEN status = 60 AND arrive_time IS NOT NULL THEN UNIX_TIMESTAMP(arrive_time) - UNIX_TIMESTAMP(create_time) END) AS avg_time_diff", //联系时效
|
||||
];
|
||||
$builder->field($fields);
|
||||
|
||||
if(!empty($filter['start_time'])){
|
||||
$builder->where('create_time','>=',$filter['start_time']);
|
||||
}
|
||||
if(!empty($filter['end_time'])){
|
||||
$builder->where('create_time','<=',$filter['start_time']);
|
||||
}
|
||||
|
||||
$builder->group('worker_id');
|
||||
return $builder->buildSql();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//图表统计
|
||||
|
||||
/**
|
||||
* @throws DbException
|
||||
*/
|
||||
public function oderSubsql($filter = []): Collection|bool|string|PDOStatement
|
||||
{
|
||||
|
||||
$orderValid = implode(',',(new Order())->tabStatus(Order::TAB_VALID));
|
||||
|
||||
//"COUNT(CASE WHEN status IN (".$orderValid.") THEN 1 END) AS ing_num",
|
||||
$fields = [
|
||||
'worker_id',
|
||||
"COUNT(CASE WHEN status = 60 THEN 1 END) AS finish_num", //完成数
|
||||
//"COUNT(CASE WHEN status IN (".$orderValid.") THEN 1 END) AS count_num", //总订单数 (排除取消 和草稿)
|
||||
"SUM(CASE WHEN status = 60 THEN total END) AS total", //成效额
|
||||
"SUM(CASE WHEN status = 60 THEN performance END) AS performance", //业绩
|
||||
"SUM(CASE WHEN status = 60 THEN cost END) AS cost", //成效额
|
||||
|
||||
// "SUM(CASE WHEN status = 60 THEN (cost + material_cost) END) AS cost_total", //总成本
|
||||
|
||||
"SUM(CASE WHEN status = 60 THEN (refund_amount + worker_refund_amount) END) AS refund_total", //退款总数
|
||||
"COUNT(CASE WHEN refund_amount > 0 OR worker_refund_amount > 0 THEN 1 END) AS refund_count", //退款订单数量
|
||||
//"AVG(CASE WHEN status > 10 THEN UNIX_TIMESTAMP(dispatch_time) - UNIX_TIMESTAMP(create_time) END) AS avg_time_diff", //派单时效
|
||||
// "SUM(CASE WHEN status = 60 THEN (field1 + field2) END) AS performance",
|
||||
];
|
||||
|
||||
$builder = (new Order())->field($fields);
|
||||
|
||||
if(!empty($filter['start_time'])){
|
||||
$builder->where('create_time','>=',$filter['start_time']);
|
||||
}
|
||||
if(!empty($filter['end_time'])){
|
||||
$builder->where('create_time','<=',$filter['start_time']);
|
||||
}
|
||||
|
||||
//->where('dispatch_admin_id','>',0);
|
||||
return $builder->group('worker_id')->buildSql();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $a
|
||||
* @param $b
|
||||
* @param int $scale
|
||||
* @param bool $is_percent
|
||||
* @return int|string
|
||||
*/
|
||||
private function _calc($a, $b, int $scale=4, bool $is_percent=false): int|string
|
||||
{
|
||||
$a = $a??0;
|
||||
$b = $b??0;
|
||||
$val = $b > 0 ? bcdiv($a,$b,$scale) : '0.00';
|
||||
|
||||
if($is_percent){
|
||||
return bcmul($val,100,2);
|
||||
}
|
||||
return $val;
|
||||
}
|
||||
|
||||
private function _toList(\think\Paginator $list)
|
||||
{
|
||||
foreach ($list as &$datum){
|
||||
//利润率 = 总业绩/总成效额
|
||||
$datum->performance_rate = $this->_calc($datum->performance,$datum->total,4,true);
|
||||
//转化率 = 完单数 / 总接单数
|
||||
$datum->trans_rate = $this->_calc($datum->finish_num,$datum->get_count,4,true);
|
||||
//变现值 = 总业绩 / 总接单数
|
||||
$datum->cash_value = $this->_calc($datum->performance,$datum->get_count,2);
|
||||
//拒单率 = 拒绝数 / 派单数
|
||||
$datum->refuse_rate = $this->_calc($datum->refuse_count,$datum->dispatch_count,4,true);
|
||||
//上门率 = 打卡数 / 接单数
|
||||
$datum->arrive_rate = $this->_calc($datum->arrive_count,$datum->get_count,4,true);
|
||||
//好评率
|
||||
$datum->good_rate = $this->_calc($datum->good_count,$datum->finish_num,4,true);
|
||||
|
||||
$datum->avg_time_diff = $this->_calc($datum->avg_time_diff,3600*24,2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 生成查询所需要的条件,排序方式
|
||||
* @param mixed $searchfields 快速查询的字段
|
||||
* @param boolean $relationSearch 是否关联查询
|
||||
* @return array
|
||||
*/
|
||||
protected function buildparams($searchfields = null, $relationSearch = null)
|
||||
{
|
||||
$searchfields = is_null($searchfields) ? $this->searchFields : $searchfields;
|
||||
$relationSearch = is_null($relationSearch) ? $this->relationSearch : $relationSearch;
|
||||
$search = $this->request->get("search", '');
|
||||
$filter = $this->request->get("filter", '');
|
||||
$op = $this->request->get("op", '', 'trim');
|
||||
$sort = $this->request->get("sort", !empty($this->model) && $this->model->getPk() ? $this->model->getPk() : 'id');
|
||||
$order = $this->request->get("order", "DESC");
|
||||
$offset = max(0, $this->request->get("offset/d", 0));
|
||||
$limit = max(0, $this->request->get("limit/d", 0));
|
||||
$limit = $limit ?: 999999;
|
||||
//新增自动计算页码
|
||||
$page = $limit ? intval($offset / $limit) + 1 : 1;
|
||||
if ($this->request->has("page")) {
|
||||
$page = max(0, $this->request->get("page/d", 1));
|
||||
}
|
||||
$this->request->get([config('paginate.var_page') => $page]);
|
||||
$filter = (array)json_decode($filter, true);
|
||||
unset($filter['daterange']);
|
||||
$op = (array)json_decode($op, true);
|
||||
$filter = $filter ? $filter : [];
|
||||
$where = [];
|
||||
$alias = [];
|
||||
$bind = [];
|
||||
$name = '';
|
||||
$aliasName = '';
|
||||
if (!empty($this->model) && $relationSearch) {
|
||||
$name = $this->model->getTable();
|
||||
$alias[$name] = Loader::parseName(basename(str_replace('\\', '/', get_class($this->model))));
|
||||
$aliasName = $alias[$name] . '.';
|
||||
}
|
||||
$sortArr = explode(',', $sort);
|
||||
foreach ($sortArr as $index => & $item) {
|
||||
$item = stripos($item, ".") === false ? $aliasName . trim($item) : $item;
|
||||
}
|
||||
unset($item);
|
||||
$sort = implode(',', $sortArr);
|
||||
$adminIds = $this->getDataLimitAdminIds();
|
||||
if (is_array($adminIds)) {
|
||||
$where[] = [$aliasName . $this->dataLimitField, 'in', $adminIds];
|
||||
}
|
||||
if ($search) {
|
||||
$searcharr = is_array($searchfields) ? $searchfields : explode(',', $searchfields);
|
||||
foreach ($searcharr as $k => &$v) {
|
||||
$v = stripos($v, ".") === false ? $aliasName . $v : $v;
|
||||
}
|
||||
unset($v);
|
||||
$where[] = [implode("|", $searcharr), "LIKE", "%{$search}%"];
|
||||
}
|
||||
$index = 0;
|
||||
foreach ($filter as $k => $v) {
|
||||
if (!preg_match('/^[a-zA-Z0-9_\-\.]+$/', $k)) {
|
||||
continue;
|
||||
}
|
||||
$sym = $op[$k] ?? '=';
|
||||
if (stripos($k, ".") === false) {
|
||||
$k = $aliasName . $k;
|
||||
}
|
||||
$v = !is_array($v) ? trim($v) : $v;
|
||||
$sym = strtoupper($op[$k] ?? $sym);
|
||||
//null和空字符串特殊处理
|
||||
if (!is_array($v)) {
|
||||
if (in_array(strtoupper($v), ['NULL', 'NOT NULL'])) {
|
||||
$sym = strtoupper($v);
|
||||
}
|
||||
if (in_array($v, ['""', "''"])) {
|
||||
$v = '';
|
||||
$sym = '=';
|
||||
}
|
||||
}
|
||||
|
||||
switch ($sym) {
|
||||
case '=':
|
||||
case '<>':
|
||||
$where[] = [$k, $sym, (string)$v];
|
||||
break;
|
||||
case 'LIKE':
|
||||
case 'NOT LIKE':
|
||||
case 'LIKE %...%':
|
||||
case 'NOT LIKE %...%':
|
||||
$where[] = [$k, trim(str_replace('%...%', '', $sym)), "%{$v}%"];
|
||||
break;
|
||||
case '>':
|
||||
case '>=':
|
||||
case '<':
|
||||
case '<=':
|
||||
$where[] = [$k, $sym, intval($v)];
|
||||
break;
|
||||
case 'FINDIN':
|
||||
case 'FINDINSET':
|
||||
case 'FIND_IN_SET':
|
||||
$v = is_array($v) ? $v : explode(',', str_replace(' ', ',', $v));
|
||||
$findArr = array_values($v);
|
||||
foreach ($findArr as $idx => $item) {
|
||||
$bindName = "item_" . $index . "_" . $idx;
|
||||
$bind[$bindName] = $item;
|
||||
$where[] = "FIND_IN_SET(:{$bindName}, `" . str_replace('.', '`.`', $k) . "`)";
|
||||
}
|
||||
break;
|
||||
case 'IN':
|
||||
case 'IN(...)':
|
||||
case 'NOT IN':
|
||||
case 'NOT IN(...)':
|
||||
$where[] = [$k, str_replace('(...)', '', $sym), is_array($v) ? $v : explode(',', $v)];
|
||||
break;
|
||||
case 'BETWEEN':
|
||||
case 'NOT BETWEEN':
|
||||
$arr = array_slice(explode(',', $v), 0, 2);
|
||||
if (stripos($v, ',') === false || !array_filter($arr, function ($v) {
|
||||
return $v != '' && $v !== false && $v !== null;
|
||||
})) {
|
||||
continue 2;
|
||||
}
|
||||
//当出现一边为空时改变操作符
|
||||
if ($arr[0] === '') {
|
||||
$sym = $sym == 'BETWEEN' ? '<=' : '>';
|
||||
$arr = $arr[1];
|
||||
} elseif ($arr[1] === '') {
|
||||
$sym = $sym == 'BETWEEN' ? '>=' : '<';
|
||||
$arr = $arr[0];
|
||||
}
|
||||
$where[] = [$k, $sym, $arr];
|
||||
break;
|
||||
case 'RANGE':
|
||||
case 'NOT RANGE':
|
||||
$v = str_replace(' - ', ',', $v);
|
||||
$arr = array_slice(explode(',', $v), 0, 2);
|
||||
if (stripos($v, ',') === false || !array_filter($arr)) {
|
||||
continue 2;
|
||||
}
|
||||
//当出现一边为空时改变操作符
|
||||
if ($arr[0] === '') {
|
||||
$sym = $sym == 'RANGE' ? '<=' : '>';
|
||||
$arr = $arr[1];
|
||||
} elseif ($arr[1] === '') {
|
||||
$sym = $sym == 'RANGE' ? '>=' : '<';
|
||||
$arr = $arr[0];
|
||||
}
|
||||
$tableArr = explode('.', $k);
|
||||
if (count($tableArr) > 1 && $tableArr[0] != $name && !in_array($tableArr[0], $alias)
|
||||
&& !empty($this->model) && $this->relationSearch) {
|
||||
//修复关联模型下时间无法搜索的BUG
|
||||
$relation = Loader::parseName($tableArr[0], 1, false);
|
||||
$alias[$this->model->$relation()->getTable()] = $tableArr[0];
|
||||
}
|
||||
$where[] = [$k, str_replace('RANGE', 'BETWEEN', $sym) . ' TIME', $arr];
|
||||
break;
|
||||
case 'NULL':
|
||||
case 'IS NULL':
|
||||
case 'NOT NULL':
|
||||
case 'IS NOT NULL':
|
||||
$where[] = [$k, strtolower(str_replace('IS ', '', $sym))];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
$index++;
|
||||
}
|
||||
if (!empty($this->model)) {
|
||||
$this->model->alias($alias);
|
||||
}
|
||||
$model = $this->model;
|
||||
$where = function ($query) use ($where, $alias, $bind, &$model) {
|
||||
if (!empty($model)) {
|
||||
$model->alias($alias);
|
||||
$model->bind($bind);
|
||||
}
|
||||
foreach ($where as $k => $v) {
|
||||
if (is_array($v)) {
|
||||
call_user_func_array([$query, 'where'], $v);
|
||||
} else {
|
||||
$query->where($v);
|
||||
}
|
||||
}
|
||||
};
|
||||
return [$where, $sort, $order, $offset, $limit, $page, $alias, $bind];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace app\admin\controller\workers;
|
||||
|
||||
use app\admin\model\Area;
|
||||
use app\admin\model\AuthGroup;
|
||||
use app\admin\model\Item;
|
||||
use app\admin\model\Order;
|
||||
|
|
@ -158,6 +159,18 @@ class Worker extends Backend
|
|||
$this->model->validateFailException()->validate($validate);
|
||||
}
|
||||
$params['admin_id'] = $this->auth->id;
|
||||
|
||||
if(!empty($params['area_id'])){
|
||||
|
||||
$area = Area::getByCode($params['area_id']);
|
||||
if($area){
|
||||
$location = getLocation($area->merge_name);
|
||||
if(!empty($location)){
|
||||
$params['lng'] = $location['lng'];
|
||||
$params['lat'] = $location['lat'];
|
||||
}
|
||||
}
|
||||
}
|
||||
$result = $this->model->allowField(true)->save($params);
|
||||
$item_map = model('item')->getAll();
|
||||
$item_map = array_column($item_map, 'level', 'id');
|
||||
|
|
|
|||
22
application/admin/lang/zh-cn/statistics/worker.php
Normal file
22
application/admin/lang/zh-cn/statistics/worker.php
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'Id' => 'ID',
|
||||
'Type' => '1 自营 2 非自营',
|
||||
'Name' => '师傅姓名',
|
||||
'Tel' => '师傅电话',
|
||||
'Status' => '师傅状态',
|
||||
'Status 1' => '激活',
|
||||
'Set status to 1' => '设为激活',
|
||||
'Status 0' => '冻结',
|
||||
'Set status to 0' => '设为冻结',
|
||||
'Area_id' => '所在地区',
|
||||
'Lng' => '经度',
|
||||
'Lat' => '纬度',
|
||||
'Location_update_time' => '位置更新时间',
|
||||
'Deposit_amount' => '保证金金额',
|
||||
'Star' => '信用(5星制)',
|
||||
'Create_time' => '创建时间',
|
||||
'Update_time' => '更新时间',
|
||||
'Deletetime' => '删除时间'
|
||||
];
|
||||
|
|
@ -47,7 +47,7 @@ class Worker extends BaseModel
|
|||
|
||||
public function area()
|
||||
{
|
||||
return $this->belongsTo('Area', 'area_id', 'area_code');
|
||||
return $this->belongsTo('area', 'area_id', 'area_code')->setEagerlyType(0);
|
||||
}
|
||||
|
||||
public function admin()
|
||||
|
|
@ -62,4 +62,12 @@ class Worker extends BaseModel
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 定义通过中间表与 roles 表的一对多关系
|
||||
public function items()
|
||||
{
|
||||
return $this->hasManyThrough(Item::class, WorkerItem::class, 'worker_id', 'item_id', 'id', 'id');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
27
application/admin/validate/Sworker.php
Normal file
27
application/admin/validate/Sworker.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\validate;
|
||||
|
||||
use think\Validate;
|
||||
|
||||
class Sworker extends Validate
|
||||
{
|
||||
/**
|
||||
* 验证规则
|
||||
*/
|
||||
protected $rule = [
|
||||
];
|
||||
/**
|
||||
* 提示消息
|
||||
*/
|
||||
protected $message = [
|
||||
];
|
||||
/**
|
||||
* 验证场景
|
||||
*/
|
||||
protected $scene = [
|
||||
'add' => [],
|
||||
'edit' => [],
|
||||
];
|
||||
|
||||
}
|
||||
|
|
@ -22,14 +22,14 @@
|
|||
<a href="javascript:;" class="btn btn-danger btn-del btn-disabled disabled {:$auth->check('aftersales/aftersale/del')?'':'hide'}" title="{:__('Delete')}" ><i class="fa fa-trash"></i> {:__('Delete')}</a>
|
||||
|
||||
-->
|
||||
<div class="dropdown btn-group {:$auth->check('aftersales/aftersale/multi')?'':'hide'}">
|
||||
<!-- <div class="dropdown btn-group {:$auth->check('aftersales/aftersale/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>-->
|
||||
|
||||
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,313 +0,0 @@
|
|||
<form id="add-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">{:__('Order_no')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-order_no" data-rule="required" class="form-control" name="row[order_no]" type="text" value="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Customer')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-customer" class="form-control" name="row[customer]" type="text">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Tel')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-tel" data-rule="required" class="form-control" name="row[tel]" type="text">
|
||||
</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="0"}checked{/in} /> {$vo}</label>
|
||||
{/foreach}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Area_id')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-area_id" data-rule="required" data-source="area/index" class="form-control selectpage" name="row[area_id]" type="text" value="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Address')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-address" data-rule="required" class="form-control" name="row[address]" type="text" value="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Lng')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-lng" class="form-control" step="0.000001" name="row[lng]" type="number">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Lat')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-lat" class="form-control" step="0.000001" name="row[lat]" type="number">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Work_tel_id')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-work_tel_id" data-rule="required" data-source="work/tel/index" class="form-control selectpage" name="row[work_tel_id]" type="text" value="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Source_shop')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-source_shop" data-rule="required" class="form-control" name="row[source_shop]" type="text" value="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Source')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-source" data-rule="required" class="form-control" name="row[source]" type="number" value="0">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Source_uid')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-source_uid" class="form-control" name="row[source_uid]" type="text">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Item_id')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-item_id" data-rule="required" data-source="item/index" class="form-control selectpage" name="row[item_id]" type="text" value="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Item_title')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-item_title" data-rule="required" class="form-control" name="row[item_title]" type="text" value="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Detail')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-detail" class="form-control" name="row[detail]" type="text">
|
||||
</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" class="form-control" name="row[remark]" type="text">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Images')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<div class="input-group">
|
||||
<input id="c-images" class="form-control" size="50" name="row[images]" type="text">
|
||||
<div class="input-group-addon no-border no-padding">
|
||||
<span><button type="button" id="faupload-images" class="btn btn-danger faupload" data-input-id="c-images" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp,image/webp" data-multiple="true" data-preview-id="p-images"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
|
||||
<span><button type="button" id="fachoose-images" class="btn btn-primary fachoose" data-input-id="c-images" data-mimetype="image/*" data-multiple="true"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
|
||||
</div>
|
||||
<span class="msg-box n-right" for="c-images"></span>
|
||||
</div>
|
||||
<ul class="row list-inline faupload-preview" id="p-images"></ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Plan_time')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-plan_time" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-use-current="true" name="row[plan_time]" type="text" value="{:date('Y-m-d H:i:s')}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Coupon_id')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-coupon_id" data-rule="required" data-source="coupon/index" class="form-control selectpage" name="row[coupon_id]" type="text" value="">
|
||||
</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" data-rule="required" class="form-control" step="0.01" name="row[total]" type="number" value="0.00">
|
||||
</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">
|
||||
<input id="c-online_amount" data-rule="required" class="form-control" step="0.01" name="row[online_amount]" type="number" value="0.00">
|
||||
</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" data-rule="required" class="form-control" step="0.01" name="row[offline_amount]" type="number" value="0.00">
|
||||
</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="0.00">
|
||||
</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">
|
||||
|
||||
<select id="c-offline_amount_type" data-rule="required" class="form-control selectpicker" name="row[offline_amount_type]">
|
||||
{foreach name="offlineAmountTypeList" 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">{:__('Discount_amount')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-discount_amount" data-rule="required" class="form-control" step="0.01" name="row[discount_amount]" type="number" value="0.00">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Refund_amount')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-refund_amount" data-rule="required" class="form-control" step="0.01" name="row[refund_amount]" type="number" value="0.00">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Worker_refund_amount')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-worker_refund_amount" data-rule="required" class="form-control" step="0.01" name="row[worker_refund_amount]" type="number" value="0.00">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Real_amount')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-real_amount" data-rule="required" class="form-control" step="0.01" name="row[real_amount]" type="number" value="0.00">
|
||||
</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="0.00">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Material_cost')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-material_cost" data-rule="required" class="form-control" step="0.01" name="row[material_cost]" type="number" value="0.00">
|
||||
</div>
|
||||
</div>
|
||||
<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" data-rule="required" class="form-control" step="0.01" name="row[performance]" type="number" value="0.00">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Cancel_reason_id')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-cancel_reason_id" data-rule="required" data-source="cancel/reason/index" class="form-control selectpage" name="row[cancel_reason_id]" type="text" value="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Cancel_detail')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-cancel_detail" class="form-control" name="row[cancel_detail]" type="text">
|
||||
</div>
|
||||
</div>
|
||||
<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" class="form-control" name="row[audit_remark]" type="text" value="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Audit_admin_id')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-audit_admin_id" data-rule="required" data-source="audit/admin/index" class="form-control selectpage" name="row[audit_admin_id]" type="text" value="">
|
||||
</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="{:date('Y-m-d H:i:s')}">
|
||||
</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="{:date('Y-m-d H:i:s')}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Delete_time')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-delete_time" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-use-current="true" name="row[delete_time]" type="text" value="{:date('Y-m-d H:i:s')}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Dispatch_type')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-dispatch_type" class="form-control" name="row[dispatch_type]" type="number">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Receive_type')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-receive_type" class="form-control" name="row[receive_type]" type="number">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Revisit_id')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-revisit_id" data-rule="required" data-source="revisit/index" class="form-control selectpage" name="row[revisit_id]" type="text" value="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Dispatch_admin_id')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-dispatch_admin_id" data-rule="required" data-source="dispatch/admin/index" class="form-control selectpage" name="row[dispatch_admin_id]" type="text" value="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Dispatch_admin_user')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-dispatch_admin_user" class="form-control" name="row[dispatch_admin_user]" type="text">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Dispatch_time')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-dispatch_time" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-use-current="true" name="row[dispatch_time]" type="text" value="{:date('Y-m-d H:i:s')}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Aftersale_id')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-aftersale_id" data-rule="required" data-source="aftersale/index" class="form-control selectpage" name="row[aftersale_id]" type="text" value="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Amount_images')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<div class="input-group">
|
||||
<input id="c-amount_images" class="form-control" size="50" name="row[amount_images]" type="text">
|
||||
<div class="input-group-addon no-border no-padding">
|
||||
<span><button type="button" id="faupload-amount_images" class="btn btn-danger faupload" data-input-id="c-amount_images" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp,image/webp" data-multiple="true" data-preview-id="p-amount_images"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
|
||||
<span><button type="button" id="fachoose-amount_images" class="btn btn-primary fachoose" data-input-id="c-amount_images" data-mimetype="image/*" data-multiple="true"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
|
||||
</div>
|
||||
<span class="msg-box n-right" for="c-amount_images"></span>
|
||||
</div>
|
||||
<ul class="row list-inline faupload-preview" id="p-amount_images"></ul>
|
||||
</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>
|
||||
|
|
@ -1,313 +0,0 @@
|
|||
<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">{:__('Order_no')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-order_no" data-rule="required" class="form-control" name="row[order_no]" type="text" value="{$row.order_no|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Customer')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-customer" class="form-control" name="row[customer]" type="text" value="{$row.customer|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Tel')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-tel" data-rule="required" class="form-control" name="row[tel]" type="text" value="{$row.tel|htmlentities}">
|
||||
</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">{:__('Area_id')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-area_id" data-rule="required" data-source="area/index" class="form-control selectpage" name="row[area_id]" type="text" value="{$row.area_id|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Address')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-address" data-rule="required" class="form-control" name="row[address]" type="text" value="{$row.address|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Lng')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-lng" class="form-control" step="0.000001" name="row[lng]" type="number" value="{$row.lng|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Lat')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-lat" class="form-control" step="0.000001" name="row[lat]" type="number" value="{$row.lat|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Work_tel_id')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-work_tel_id" data-rule="required" data-source="work/tel/index" class="form-control selectpage" name="row[work_tel_id]" type="text" value="{$row.work_tel_id|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Source_shop')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-source_shop" data-rule="required" class="form-control" name="row[source_shop]" type="text" value="{$row.source_shop|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Source')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-source" data-rule="required" class="form-control" name="row[source]" type="number" value="{$row.source|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Source_uid')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-source_uid" class="form-control" name="row[source_uid]" type="text" value="{$row.source_uid|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Item_id')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-item_id" data-rule="required" data-source="item/index" class="form-control selectpage" name="row[item_id]" type="text" value="{$row.item_id|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Item_title')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-item_title" data-rule="required" class="form-control" name="row[item_title]" type="text" value="{$row.item_title|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Detail')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-detail" class="form-control" name="row[detail]" type="text" value="{$row.detail|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" 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">{:__('Images')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<div class="input-group">
|
||||
<input id="c-images" class="form-control" size="50" name="row[images]" type="text" value="{$row.images|htmlentities}">
|
||||
<div class="input-group-addon no-border no-padding">
|
||||
<span><button type="button" id="faupload-images" class="btn btn-danger faupload" data-input-id="c-images" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp,image/webp" data-multiple="true" data-preview-id="p-images"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
|
||||
<span><button type="button" id="fachoose-images" class="btn btn-primary fachoose" data-input-id="c-images" data-mimetype="image/*" data-multiple="true"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
|
||||
</div>
|
||||
<span class="msg-box n-right" for="c-images"></span>
|
||||
</div>
|
||||
<ul class="row list-inline faupload-preview" id="p-images"></ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Plan_time')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-plan_time" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-use-current="true" name="row[plan_time]" type="text" value="{$row.plan_time}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Coupon_id')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-coupon_id" data-rule="required" data-source="coupon/index" class="form-control selectpage" name="row[coupon_id]" type="text" value="{$row.coupon_id|htmlentities}">
|
||||
</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" 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">
|
||||
<input id="c-online_amount" data-rule="required" class="form-control" step="0.01" name="row[online_amount]" type="number" value="{$row.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" data-rule="required" class="form-control" step="0.01" name="row[offline_amount]" type="number" value="{$row.offline_amount|htmlentities}">
|
||||
</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_type')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
|
||||
<select id="c-offline_amount_type" data-rule="required" class="form-control selectpicker" name="row[offline_amount_type]">
|
||||
{foreach name="offlineAmountTypeList" item="vo"}
|
||||
<option value="{$key}" {in name="key" value="$row.offline_amount_type"}selected{/in}>{$vo}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Discount_amount')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-discount_amount" data-rule="required" class="form-control" step="0.01" name="row[discount_amount]" type="number" value="{$row.discount_amount|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Refund_amount')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-refund_amount" data-rule="required" class="form-control" step="0.01" name="row[refund_amount]" type="number" value="{$row.refund_amount|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Worker_refund_amount')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-worker_refund_amount" data-rule="required" class="form-control" step="0.01" name="row[worker_refund_amount]" type="number" value="{$row.worker_refund_amount|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Real_amount')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-real_amount" data-rule="required" class="form-control" step="0.01" name="row[real_amount]" type="number" value="{$row.real_amount|htmlentities}">
|
||||
</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}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Material_cost')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-material_cost" data-rule="required" class="form-control" step="0.01" name="row[material_cost]" type="number" value="{$row.material_cost|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<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" data-rule="required" class="form-control" step="0.01" name="row[performance]" type="number" value="{$row.performance|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Cancel_reason_id')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-cancel_reason_id" data-rule="required" data-source="cancel/reason/index" class="form-control selectpage" name="row[cancel_reason_id]" type="text" value="{$row.cancel_reason_id|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Cancel_detail')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-cancel_detail" class="form-control" name="row[cancel_detail]" type="text" value="{$row.cancel_detail|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<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" class="form-control" name="row[audit_remark]" type="text" value="{$row.audit_remark|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Audit_admin_id')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-audit_admin_id" data-rule="required" data-source="audit/admin/index" class="form-control selectpage" name="row[audit_admin_id]" type="text" value="{$row.audit_admin_id|htmlentities}">
|
||||
</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">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Delete_time')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-delete_time" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-use-current="true" name="row[delete_time]" type="text" value="{$row.delete_time}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Dispatch_type')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-dispatch_type" class="form-control" name="row[dispatch_type]" type="number" value="{$row.dispatch_type|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Receive_type')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-receive_type" class="form-control" name="row[receive_type]" type="number" value="{$row.receive_type|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Revisit_id')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-revisit_id" data-rule="required" data-source="revisit/index" class="form-control selectpage" name="row[revisit_id]" type="text" value="{$row.revisit_id|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Dispatch_admin_id')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-dispatch_admin_id" data-rule="required" data-source="dispatch/admin/index" class="form-control selectpage" name="row[dispatch_admin_id]" type="text" value="{$row.dispatch_admin_id|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Dispatch_admin_user')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-dispatch_admin_user" class="form-control" name="row[dispatch_admin_user]" type="text" value="{$row.dispatch_admin_user|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Dispatch_time')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-dispatch_time" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-use-current="true" name="row[dispatch_time]" type="text" value="{$row.dispatch_time}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Aftersale_id')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-aftersale_id" data-rule="required" data-source="aftersale/index" class="form-control selectpage" name="row[aftersale_id]" type="text" value="{$row.aftersale_id|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Amount_images')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<div class="input-group">
|
||||
<input id="c-amount_images" class="form-control" size="50" name="row[amount_images]" type="text" value="{$row.amount_images|htmlentities}">
|
||||
<div class="input-group-addon no-border no-padding">
|
||||
<span><button type="button" id="faupload-amount_images" class="btn btn-danger faupload" data-input-id="c-amount_images" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp,image/webp" data-multiple="true" data-preview-id="p-amount_images"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
|
||||
<span><button type="button" id="fachoose-amount_images" class="btn btn-primary fachoose" data-input-id="c-amount_images" data-mimetype="image/*" data-multiple="true"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
|
||||
</div>
|
||||
<span class="msg-box n-right" for="c-amount_images"></span>
|
||||
</div>
|
||||
<ul class="row list-inline faupload-preview" id="p-amount_images"></ul>
|
||||
</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>
|
||||
361
application/admin/view/statistics/worker/index.html
Normal file
361
application/admin/view/statistics/worker/index.html
Normal file
|
|
@ -0,0 +1,361 @@
|
|||
<style>
|
||||
.sm-st {
|
||||
background: #fff;
|
||||
padding: 20px;
|
||||
-webkit-border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.sm-st-icon {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
display: inline-block;
|
||||
line-height: 60px;
|
||||
text-align: center;
|
||||
font-size: 30px;
|
||||
background: #eee;
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
float: left;
|
||||
margin-right: 10px;
|
||||
color: #fff;
|
||||
}
|
||||
.sm-st-info {
|
||||
padding-top: 2px;
|
||||
}
|
||||
|
||||
.sm-st-info span {
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.orange {
|
||||
background: #fa8564 !important;
|
||||
}
|
||||
|
||||
.tar {
|
||||
background: #45cf95 !important;
|
||||
}
|
||||
|
||||
.sm-st .green {
|
||||
background: #86ba41 !important;
|
||||
}
|
||||
|
||||
.pink {
|
||||
background: #AC75F0 !important;
|
||||
}
|
||||
|
||||
.yellow-b {
|
||||
background: #fdd752 !important;
|
||||
}
|
||||
|
||||
.stat-elem {
|
||||
|
||||
background-color: #fff;
|
||||
padding: 18px;
|
||||
border-radius: 40px;
|
||||
|
||||
}
|
||||
|
||||
.stat-info {
|
||||
text-align: center;
|
||||
background-color: #fff;
|
||||
border-radius: 5px;
|
||||
margin-top: -5px;
|
||||
padding: 8px;
|
||||
-webkit-box-shadow: 0 1px 0px rgba(0, 0, 0, 0.05);
|
||||
box-shadow: 0 1px 0px rgba(0, 0, 0, 0.05);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.stat-icon {
|
||||
text-align: center;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.st-red {
|
||||
background-color: #F05050;
|
||||
}
|
||||
|
||||
.st-green {
|
||||
background-color: #27C24C;
|
||||
}
|
||||
|
||||
.st-violet {
|
||||
background-color: #7266ba;
|
||||
}
|
||||
|
||||
.st-blue {
|
||||
background-color: #23b7e5;
|
||||
}
|
||||
|
||||
.stats .stat-icon {
|
||||
color: #28bb9c;
|
||||
display: inline-block;
|
||||
font-size: 26px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
width: 50px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.stat {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.stat .value {
|
||||
font-size: 20px;
|
||||
line-height: 24px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.stat .name {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
.stat.lg .value {
|
||||
font-size: 26px;
|
||||
line-height: 28px;
|
||||
}
|
||||
|
||||
.stat-col {
|
||||
margin:0 0 10px 0;
|
||||
}
|
||||
.stat.lg .name {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.stat-col .progress {
|
||||
height: 2px;
|
||||
}
|
||||
|
||||
.stat-col .progress-bar {
|
||||
line-height: 2px;
|
||||
height: 2px;
|
||||
}
|
||||
|
||||
.item {
|
||||
padding: 30px 0;
|
||||
}
|
||||
|
||||
|
||||
#statistics .panel {
|
||||
min-height: 150px;
|
||||
}
|
||||
|
||||
#statistics .panel h5 {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<div class="panel panel-default panel-intro">
|
||||
<div class="panel-heading">
|
||||
<!--<div class="panel-lead"><em>多表格(Multitable)</em>用于展示在一个页面展示多个表格数据,并且每次切换时刷新</div>-->
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="active"><a data-val="first" href="#first" data-toggle="tab">统计图表</a></li>
|
||||
<li><a href="#second" data-val="second" data-toggle="tab">统计列表</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="panel-body" style="height: 100%">
|
||||
<div id="myTabContent" class="tab-content" style="height: 100%">
|
||||
<div class="tab-pane fade active in" style="height: 100%" id="first">
|
||||
<section class="connectedSortable" style="height: 100%">
|
||||
|
||||
<div class="nav-tabs-custom charts-custom">
|
||||
<!-- Tabs within a box -->
|
||||
<ul class="nav nav-tabs pull-right">
|
||||
<li class="active"><a href="#bar-chart" data-toggle="tab">地图分布</a></li>
|
||||
<!-- <li><a href="#pie-chart" data-toggle="tab">饼图</a></li>-->
|
||||
|
||||
<li class="pull-left header"><i class="fa fa-inbox"></i> 师傅统计图</li>
|
||||
</ul>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-3 col-xs-6">
|
||||
<div class="sm-st clearfix">
|
||||
<span class="sm-st-icon st-blue"><i class="fa fa-users"></i></span>
|
||||
<div class="sm-st-info">
|
||||
<span>{$count}/{$active_count}</span>
|
||||
师傅总数/活跃数
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6">
|
||||
<div class="sm-st clearfix">
|
||||
<span class="sm-st-icon st-green"><i class="fa fa-users"></i></span>
|
||||
<div class="sm-st-info">
|
||||
<span>{$add_count_1}/{$add_count_7}</span>
|
||||
今日新增/7天新增
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6">
|
||||
<div class="sm-st clearfix">
|
||||
<span class="sm-st-icon st-violet"><i class="fa fa-users"></i></span>
|
||||
<div class="sm-st-info">
|
||||
<span>{$todo_count}/{$ing_count}/{$check_count}</span>
|
||||
待接单/进行中/待验收
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6">
|
||||
<div class="sm-st clearfix">
|
||||
<span class="sm-st-icon st-red"><i class="fa fa-users"></i></span>
|
||||
<div class="sm-st-info">
|
||||
<span>{$aftersale_count}</span>
|
||||
待处理售后
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="tab-content no-padding" style="height: 100%">
|
||||
<div class="chart tab-pane active" id="bar-chart" style="width: 100%; min-height:600px;height: 100%">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="second">
|
||||
<table id="table2" class="table table-striped table-bordered table-hover" width="100%">
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 先加载 mapv -->
|
||||
<script src="https://mapv.baidu.com/build/mapv.min.js"></script>
|
||||
|
||||
<!-- 再加载 mapvgl -->
|
||||
<script src="https://code.bdstatic.com/npm/mapvgl@1.0.0-beta.189/dist/mapvgl.min.js"></script>
|
||||
|
||||
<!-- 最后加载百度地图并回调 -->
|
||||
<!-- 加载百度地图 GL -->
|
||||
<script>
|
||||
|
||||
const rawDataStr = '{$locationData}';
|
||||
// 先解析成数组
|
||||
const rawData = JSON.parse(rawDataStr);
|
||||
window.initMap = function () {
|
||||
const map = new BMapGL.Map("bar-chart");
|
||||
map.centerAndZoom(new BMapGL.Point(104.0665, 30.5728), 6);
|
||||
map.enableScrollWheelZoom(true);
|
||||
|
||||
map.addEventListener('tilesloaded', function () {
|
||||
const view = new mapvgl.View({ map });
|
||||
|
||||
// ✅ 写死的点数据(10个城市)
|
||||
/*const data = [
|
||||
{ geometry: { type: 'Point', coordinates: [116.4074, 39.9042] } }, // 北京
|
||||
{ geometry: { type: 'Point', coordinates: [121.4737, 31.2304] } }, // 上海
|
||||
{ geometry: { type: 'Point', coordinates: [113.2644, 23.1291] } }, // 广州
|
||||
{ geometry: { type: 'Point', coordinates: [114.0579, 22.5431] } }, // 深圳
|
||||
{ geometry: { type: 'Point', coordinates: [117.2000, 39.1333] } }, // 天津
|
||||
{ geometry: { type: 'Point', coordinates: [120.1551, 30.2741] } }, // 杭州
|
||||
{ geometry: { type: 'Point', coordinates: [104.0665, 30.5728] } }, // 成都
|
||||
{ geometry: { type: 'Point', coordinates: [106.5516, 29.5630] } }, // 重庆
|
||||
{ geometry: { type: 'Point', coordinates: [108.9480, 34.2632] } }, // 西安
|
||||
{ geometry: { type: 'Point', coordinates: [115.8582, 28.6829] } } // 南昌
|
||||
];*/
|
||||
|
||||
const data = rawData.map(item => ({
|
||||
geometry: {
|
||||
type: 'Point',
|
||||
coordinates: item
|
||||
}
|
||||
}));
|
||||
|
||||
// 根据聚合区域内的点数决定颜色(数量多,颜色深)
|
||||
const gradient = {
|
||||
0: 'rgba(162, 180, 73, 0.7)', // 浅绿
|
||||
0.3: 'rgba(121, 153, 0, 0.8)', // 中绿
|
||||
0.7: 'rgba(99, 121, 0, 0.9)', // 深绿
|
||||
1.0: 'rgba(66, 77, 0, 1)' // 更深绿
|
||||
};
|
||||
|
||||
// 定义聚合层
|
||||
const clusterLayer = new mapvgl.ClusterLayer({
|
||||
minSize: 30,
|
||||
maxSize: 50,
|
||||
clusterRadius: 150,
|
||||
gradient: gradient, // 设置颜色渐变
|
||||
showText: true,
|
||||
textOptions: {
|
||||
fontSize: 12,
|
||||
color: 'white',
|
||||
format: function (count) {
|
||||
if (count === 0) return ''; // 数量为0时不展示
|
||||
return count >= 1000 ? Math.round(count / 100) / 10 + 'k' : count; // 格式化数字
|
||||
}
|
||||
},
|
||||
iconOptions: {
|
||||
fillStyle: 'rgba(162, 180, 73, 0.7)', // 主色调:浅绿色
|
||||
lineWidth: 1,
|
||||
strokeStyle: 'rgba(121, 153, 0, 1)', // 边框:绿色
|
||||
radius: 19, // 圆形点
|
||||
shadowBlur: 5, // 阴影效果
|
||||
shadowColor: 'rgba(244, 255, 204, 0.7)', // 阴影颜色
|
||||
},
|
||||
// 让每个点有自己的外观样式
|
||||
icon: function (count) {
|
||||
// 使用样式文本:点的数量越多,颜色越深
|
||||
return {
|
||||
backgroundColor: `rgba(121, 153, 0, 0.7)`, // 点背景颜色
|
||||
height: '38px', // 高度
|
||||
width: '38px', // 宽度
|
||||
border: '1px solid rgb(121, 153, 0)', // 边框
|
||||
borderRadius: '19px', // 边角半径(圆形)
|
||||
boxShadow: 'rgb(244, 255, 204) 0px 0px 5px', // 阴影
|
||||
lineHeight: '38px', // 行高
|
||||
color: 'rgb(244, 255, 204)', // 字体颜色(淡黄)
|
||||
fontSize: '14px', // 字体大小
|
||||
textAlign: 'center', // 文本居中
|
||||
cursor: 'pointer' // 鼠标样式为指针
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// 添加数据并展示
|
||||
view.addLayer(clusterLayer);
|
||||
clusterLayer.setData(data);
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<script src="https://api.map.baidu.com/api?type=webgl&v=1.0&ak={$mapkey}&callback=initMap"></script>
|
||||
|
||||
<!--
|
||||
<script id="sourcetpl" type="text/html">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<div class="form-inline" data-toggle="cxselect" data-selects="province,city,area">
|
||||
<select style="width: 100px;" class="province form-control" name="province_id" data-url="ajax/area" ></select>
|
||||
<input type="hidden" class="operate" data-name="province_id" value="=" />
|
||||
<select style="width: 100px;" class="city form-control" name="city_id" data-url="ajax/area" data-query-name="province"></select>
|
||||
<input type="hidden" class="operate" data-name="city_id" value="=" />
|
||||
<!– <select class="area form-control" name="area_id" data-url="ajax/area" data-query-name="city"></select>
|
||||
<input type="hidden" class="operate" data-name="area_id" value="=" />–>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>-->
|
||||
|
|
@ -130,6 +130,8 @@ class OrderLogic
|
|||
|
||||
if($nocancelOrder){
|
||||
$order = Order::where('id',$dispatch->order_id)->where('status',Order::STATUS_DISPATCHED)->find();
|
||||
$order->worker_id = 0;
|
||||
$order->save();
|
||||
if(empty($order)){
|
||||
throw new Exception('未找到关联订单');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ class CheckOrderDispatchCommand extends Command
|
|||
//1修改为超时
|
||||
$item->status = OrderDispatch::STATUS_OVERTIME;
|
||||
$item->save();
|
||||
$params = ['dispatch'=>$item,'remark'=>'系统自动处理,任务超时'];
|
||||
$params = ['dispatch'=>$item,'remark'=>'系统自动检测,任务超时'];
|
||||
Hook::listen('order_dispatch_change',$params);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -175,8 +175,8 @@ class WorkerApi extends BaseService
|
|||
'time' => Request::instance()->server('REQUEST_TIME'),
|
||||
'data' => $data,
|
||||
];
|
||||
// 如果未设置类型则自动判断
|
||||
$type = $type ? $type : ($this->request->param(config('var_jsonp_handler')) ? 'jsonp' : $this->responseType);
|
||||
// 如果未设置类型则使用默认类型判断
|
||||
$type = $type ? : $this->responseType;
|
||||
|
||||
if (isset($header['statuscode'])) {
|
||||
$code = $header['statuscode'];
|
||||
|
|
|
|||
|
|
@ -214,6 +214,9 @@ return [
|
|||
// 是否自动开启 SESSION
|
||||
'auto_start' => true,
|
||||
|
||||
//有效期
|
||||
'expire' => 3600*24,
|
||||
|
||||
'type' => 'redis',
|
||||
'host' => Env::get('redis.redis_host'), // Redis 服务器地址
|
||||
'port' => Env::get('redis.redis_port'), // Redis 端口
|
||||
|
|
|
|||
5
application/extra/map.php
Normal file
5
application/extra/map.php
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'baidu_app_key' => 'UQjHtbQQoDQRpAE5QLGFvC8exM6rcu69'
|
||||
];
|
||||
|
|
@ -6,6 +6,8 @@ use app\common\controller\WorkerApi;
|
|||
|
||||
class Common extends WorkerApi
|
||||
{
|
||||
protected $noNeedLogin = ['config'];
|
||||
|
||||
public function ossParams()
|
||||
{
|
||||
$name = $this->request->post('name');
|
||||
|
|
@ -22,4 +24,24 @@ class Common extends WorkerApi
|
|||
|
||||
$this->success('获取成功', $params);
|
||||
}
|
||||
|
||||
public function config()
|
||||
{
|
||||
$res = [
|
||||
'user_agreement' => $this->getUserAgreement(),
|
||||
'privacy_policy' => $this->getPrivacyPolicy(),
|
||||
];
|
||||
|
||||
$this->success('请求成功', $res);
|
||||
}
|
||||
|
||||
private function getUserAgreement(): string
|
||||
{
|
||||
return '<span style="box-sizing: border-box;"><strong style="box-sizing: border-box;" >超邦手用户服务协议</strong></span><br style="box-sizing: border-box;"/><br style="box-sizing: border-box;"/><span style="color: var(--summaryColor); box-sizing: border-box;">生效日期: 2025年3月3日</span><br style="box-sizing: border-box;"/><br style="box-sizing: border-box;"/><span style="font-size: 14px; box-sizing: border-box;">欢迎您使用“超邦手”小程序!本协议由四川亿灵匠网络科技有限公司(以下简称“我们”或“平台”)与您(以下简称“用户”)签订,适用于您在超邦手小程序上的所有活动。<br style="box-sizing: border-box;"/><br style="box-sizing: border-box;"/><strong style="box-sizing: border-box;">一、服务内容</strong><br style="box-sizing: border-box;"/><br style="box-sizing: border-box;"/>平台服务: 我们为维修师傅和用户提供信息匹配平台。用户可以在平台上发布维修需求,维修师傅可自由选择接单。<br style="box-sizing: border-box;"/><br style="box-sizing: border-box;"/>中介性质: 平台仅提供信息发布和撮合服务,不直接参与维修过程。<br style="box-sizing: border-box;"/><br style="box-sizing: border-box;"/><strong style="box-sizing: border-box;">二、用户义务</strong><br style="box-sizing: border-box;"/><br style="box-sizing: border-box;"/>真实信息: 用户须提供真实有效的信息进行注册,不得冒用他人身份。<br style="box-sizing: border-box;"/><br style="box-sizing: border-box;"/>遵守法律: 不得在平台上发布违法信息或从事不正当活动。<br style="box-sizing: border-box;"/><br style="box-sizing: border-box;"/>订单履约: 维修师傅须按约定完成服务,不得敷衍了事或拒绝履约。<br style="box-sizing: border-box;"/><br style="box-sizing: border-box;"/><strong style="box-sizing: border-box;">三、费用与支付</strong><br style="box-sizing: border-box;"/><br style="box-sizing: border-box;"/>支付方式: 用户在下单后通过平台支付维修费用。平台将向师傅支付相应服务费用。<br style="box-sizing: border-box;"/><br style="box-sizing: border-box;"/>平台抽佣: 平台会根据订单金额收取一定比例的佣金。<br style="box-sizing: border-box;"/><br style="box-sizing: border-box;"/><strong style="box-sizing: border-box;">四、争议解决</strong><br style="box-sizing: border-box;"/><br style="box-sizing: border-box;"/>协商处理: 用户与维修师傅之间发生争议,应优先协商解决。<br style="box-sizing: border-box;"/><br style="box-sizing: border-box;"/>平台介入: 无法协商一致的,可申请平台介入调解。<br style="box-sizing: border-box;"/><br style="box-sizing: border-box;"/><strong style="box-sizing: border-box;">五、协议的修改与终止</strong><br style="box-sizing: border-box;"/><br style="box-sizing: border-box;"/>修改: 我们有权根据实际情况对本协议进行修订,并通过平台公告的方式通知。<br style="box-sizing: border-box;"/><br style="box-sizing: border-box;"/>终止: 用户违反本协议的,我们有权终止服务。</span>';
|
||||
}
|
||||
|
||||
private function getPrivacyPolicy(): string
|
||||
{
|
||||
return '<span style="font-size: 17px;"><strong>超邦手隐私政策</strong></span><span style="font-size:14px;" ><br/><br/><span style="color: var(--summaryColor); font-size: 14px;" mark-selection="">生效日期: 2025年3月3日</span><br/><br/>我们深知个人信息对您的重要性,并承诺依法保护您的隐私。请您在使用“超邦手”小程序之前,仔细阅读本隐私政策。<br/><br/><strong>一、我们如何收集和使用信息</strong><br/><br/>基本信息: 在您注册账号时,我们会收集您的姓名、手机号等信息。<br/><br/>订单信息: 您在使用平台发布需求或接单时,我们会收集订单详情、地址等信息。<br/><br/>设备信息: 为保障您的账号安全,我们会收集设备型号、操作系统等信息。<br/><br/><strong>二、信息的共享与转让<br/></strong><br/>服务提供: 为促成交易的完成,平台会将必要信息共享给维修师傅。<br/><br/>法律要求: 在法律要求的情况下,我们可能向相关执法部门提供您的信息。<br/><br/><strong>三、信息的存储和保护</strong><br/><br/>存储期限: 您的个人信息将存储在符合安全标准的服务器中,保存期限不超过法律规定的时间。<br/><br/>安全保护: 我们采取严格的安全措施,防止您的信息被非法访问、使用或泄露。<br/><br/><strong>四、您的权利</strong><br/><br/>查询和更正: 您可以在小程序中访问、更正或删除您的个人信息。<br/><br/>撤回同意: 您有权撤回对我们收集和处理您信息的同意。<br/><br/><strong>五、联系我们</strong><br/><br/>如您对本隐私政策有任何疑问,可通过超邦手小程序的客服功能联系我们。<br/><br/><strong>四川亿灵匠网络科技有限公司</strong></span>';
|
||||
}
|
||||
}
|
||||
|
|
@ -10,7 +10,6 @@ class Worker extends WorkerApi
|
|||
|
||||
/**
|
||||
* 微信登录
|
||||
* @return void
|
||||
*/
|
||||
public function login()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -12,9 +12,9 @@ define([], function () {
|
|||
var zoom_id = $(that).data("zoom-id") ? $(that).data("zoom-id") : "";
|
||||
var lat = lat_id ? $("#" + lat_id).val() : '';
|
||||
var lng = lng_id ? $("#" + lng_id).val() : '';
|
||||
var city_code = $("#area_id").val();
|
||||
var city_code = $("#c-city").val();
|
||||
var zoom = zoom_id ? $("#" + zoom_id).val() : '';
|
||||
var url = "/addons/address/index/select?1=1";
|
||||
var url = "/addons/address/index/select?a=1";
|
||||
url += (lat && lng) ? 'lat=' + lat + '&lng=' + lng +
|
||||
(input_id ? "&address=" + $("#" + input_id).val() : "")
|
||||
+(zoom ? "&zoom=" + zoom : "") : ''
|
||||
|
|
|
|||
|
|
@ -53,6 +53,8 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
|
|||
{field: 'images', title: __('Images'), operate: false, events: Table.api.events.image, formatter: Table.api.formatter.images},
|
||||
{field: 'remark', title: __('Remark'), operate: false, table: table, class: 'autocontent', formatter: Table.api.formatter.content},
|
||||
|
||||
{field: 'dispatch_admin_user', title: __('派单员'), operate: '='},
|
||||
|
||||
//{field: 'admin_id', title: __('Admin_id')},
|
||||
{field: 'admin_user', title: __('Admin_user'), operate: '='},
|
||||
//{field: 'handle_admin_id', title: __('Handle_admin_id')},
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts', 'echarts-t
|
|||
columns: [
|
||||
[
|
||||
//{field: 'id', title: __('Id')},
|
||||
{field: 'id', title: __('ID'),visible:false,operate: false},
|
||||
{field: 'id', title: __('ID'),visible:true,operate: false},
|
||||
{field: 'admin_user', title: __('派单员'),operate: "LIKE"},
|
||||
{field: 'count_num', title: __('总订单数'),operate: false},
|
||||
{field: 'finish_num', title: __('完单数'),operate: false},
|
||||
|
|
@ -45,7 +45,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts', 'echarts-t
|
|||
{field: 'performance_avg', title: __('客单利润(¥)'), operate: false},
|
||||
{field: 'total_avg', title: __('客单价(¥)'), operate: false},
|
||||
|
||||
{field: 'avg_time_diff', title: __('派单时效(小时)'), operate: false},
|
||||
{field: 'avg_time_diff', title: __('派单时效(天)'), operate: false},
|
||||
|
||||
//{field: 'admin_user', title: __('派单员'),operate: "LIKE",visible:false},
|
||||
//{field: 'city_name', title: __('城市'),operate: "LIKE",visible:false},
|
||||
|
|
@ -57,9 +57,27 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts', 'echarts-t
|
|||
datetimeFormat: "YYYY-MM-DD",
|
||||
//defaultValue:today()+' - '+today(),
|
||||
data:'autocomplete="off" data-local={"format":"YYYY-MM-DD"}',
|
||||
visible:false},
|
||||
|
||||
// {field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate}
|
||||
visible:false,
|
||||
defaultValue: Config.default_daterange
|
||||
},
|
||||
{field: 'operate', title: __('Operate'), table: table2, events: Table.api.events.operate, formatter: Table.api.formatter.operate,
|
||||
buttons: [
|
||||
{
|
||||
name: 'aftersales',
|
||||
text:"售后列表",
|
||||
title:"售后列表",
|
||||
icon: 'fa fa-list',
|
||||
url: function(row){
|
||||
return 'aftersales/aftersale/index?from=2&man_id='+row.id;
|
||||
},
|
||||
extend: 'data-toggle="tooltip" data-container="body"',
|
||||
classname: 'btn btn-xs btn-default btn-dialog',
|
||||
visible:function(row){
|
||||
return true;
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
});
|
||||
|
|
@ -105,6 +123,9 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts', 'echarts-t
|
|||
// ]
|
||||
// }
|
||||
|
||||
const headers = response[0];
|
||||
const units = ['元', '%', '%', '']; // 如果你有单位可以一起拼接
|
||||
|
||||
var barChart = Echarts.init(document.getElementById('bar-chart'), 'walden');
|
||||
var option = {
|
||||
legend: {},
|
||||
|
|
@ -112,14 +133,30 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts', 'echarts-t
|
|||
dataset: {
|
||||
source: response
|
||||
},
|
||||
xAxis: { type: 'category' },
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
axisLabel: {
|
||||
show: true // 隐藏“系统”
|
||||
},
|
||||
axisTick: { show: false },
|
||||
axisLine: { show: false }
|
||||
},
|
||||
yAxis: {},
|
||||
series: [
|
||||
{ type: 'bar' },
|
||||
{ type: 'bar' },
|
||||
{ type: 'bar' },
|
||||
{ type: 'bar' }
|
||||
]
|
||||
series: headers.slice(1).map((title, i) => ({
|
||||
type: 'bar',
|
||||
label: {
|
||||
show: true,
|
||||
position: 'top',
|
||||
formatter: function (params) {
|
||||
const value = params.value[i + 1]; // 因为第一列是“派单员”
|
||||
const unit = units[i] || '';
|
||||
return `${value} ${unit}`; // 显示数值 + 单位
|
||||
}
|
||||
},
|
||||
itemStyle: {
|
||||
borderRadius: 4
|
||||
}
|
||||
}))
|
||||
};
|
||||
barChart.setOption(option);
|
||||
},
|
||||
|
|
@ -186,6 +223,11 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts', 'echarts-t
|
|||
edit: function () {
|
||||
Controller.api.bindevent();
|
||||
},
|
||||
|
||||
aftersales: function () {
|
||||
Controller.api.bindevent();
|
||||
},
|
||||
|
||||
api: {
|
||||
bindevent: function () {
|
||||
Form.api.bindevent($("form[role=form]"));
|
||||
|
|
|
|||
251
public/assets/js/backend/statistics/worker.js
Normal file
251
public/assets/js/backend/statistics/worker.js
Normal file
|
|
@ -0,0 +1,251 @@
|
|||
define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts', 'echarts-theme', 'template','addtabs','moment'], function ($, undefined, Backend, Table, Form,Echarts,undefined,Template,Datatable,Moment) {
|
||||
|
||||
var Controller = {
|
||||
|
||||
index: function () {
|
||||
//绑定事件
|
||||
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
|
||||
var $targetPanel = $($(this).attr("href"));
|
||||
var tabVal = $(this).data('val');
|
||||
|
||||
if (tabVal === 'second') {
|
||||
// 当切换到“统计列表”时,自动刷新表格
|
||||
//$targetPanel.find(".btn-refresh").trigger("click");
|
||||
// 初始化表格参数配置
|
||||
Table.api.init();
|
||||
// 表格2
|
||||
var table2 = $("#table2");
|
||||
table2.bootstrapTable({
|
||||
url: 'statistics/worker/index' + location.search,
|
||||
toolbar: '#toolbar1',
|
||||
sortName: 'id',
|
||||
search: false,
|
||||
commonSearch:true,
|
||||
visible: false,
|
||||
showToggle: false,
|
||||
showColumns: false,
|
||||
showExport: true,
|
||||
searchFormVisible:true,
|
||||
columns: [
|
||||
[
|
||||
//{field: 'id', title: __('Id')},
|
||||
{field: 'id', title: __('ID'),visible:true},
|
||||
{field: 'name', title: __('姓名'),operate: "="},
|
||||
{field: 'tel', title: __('电话'),operate: "="},
|
||||
{field: 'area.name', title: __('城市'),operate: false},
|
||||
{field: 'star', title: __('评分'),operate: false},
|
||||
{field: 'performance', title: __('总业绩(¥)'), operate: false},
|
||||
{field: 'get_count', title: __('接单数'),operate: false},
|
||||
{field: 'finish_num', title: __('完单数'),operate: false},
|
||||
{field: 'cost', title: __('收入(¥)'), operate: false},
|
||||
{field: 'performance_rate', title: __('利润率(%)'), operate: false},
|
||||
{field: 'trans_rate', title: __('转化率(%)'), operate: false},
|
||||
{field: 'cash_value', title: __('变现值'), operate: false},
|
||||
{field: 'refuse_rate', title: __('拒单率(%)'), operate: false},
|
||||
{field: 'arrive_rate', title: __('上门率(%)'), operate: false},
|
||||
{field: 'good_rate', title: __('好评率(%)'), operate: false},
|
||||
|
||||
//{field: 'refund_total', title: __('退款金额(¥)'), operate: false},
|
||||
{field: 'refund_count', title: __('退款单数'), operate: false},
|
||||
|
||||
|
||||
{field: 'avg_time_diff', title: __('联系时效(天)'), operate: false},
|
||||
|
||||
//{field: 'admin_user', title: __('派单员'),operate: "LIKE",visible:false},
|
||||
//{field: 'city_name', title: __('城市'),operate: "LIKE",visible:false},
|
||||
//{field: 'city_name', title: __('城市'),operate: "LIKE",visible:false},
|
||||
|
||||
/*{field: 'area', title: __('城市'), searchList: function (column) {
|
||||
return Template('sourcetpl', {});
|
||||
}
|
||||
},
|
||||
*/
|
||||
{field: 'area.merge_name', title: __('地区'),operate: 'LIKE',visible:false},
|
||||
|
||||
{field: 'daterange', title: __('时间筛选'), addclass:'datetimerange',
|
||||
autocomplete:false,
|
||||
operate: "RANGE",
|
||||
datetimeFormat: "YYYY-MM-DD",
|
||||
//defaultValue:today()+' - '+today(),
|
||||
data:'autocomplete="off" data-local={"format":"YYYY-MM-DD"}',
|
||||
visible:false,
|
||||
defaultValue: Config.default_daterange
|
||||
},
|
||||
|
||||
{field: 'operate', title: __('Operate'), table: table2, events: Table.api.events.operate, formatter: Table.api.formatter.operate,
|
||||
buttons: [
|
||||
{
|
||||
name: 'aftersales',
|
||||
text:"售后列表",
|
||||
title:"售后列表",
|
||||
icon: 'fa fa-list',
|
||||
url: function(row){
|
||||
return 'aftersales/aftersale/index?from=3&man_id='+row.id;
|
||||
},
|
||||
extend: 'data-toggle="tooltip" data-container="body"',
|
||||
classname: 'btn btn-xs btn-default btn-dialog',
|
||||
visible:function(row){
|
||||
return true;
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
});
|
||||
// 为表格2绑定事件
|
||||
Table.api.bindevent(table2);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
// 触发 tab 后发起 ajax 获取图表数据
|
||||
$('ul.nav-tabs li.active a[data-toggle="tab"]').on("shown.bs.tab", function () {
|
||||
getChartData();
|
||||
});
|
||||
|
||||
|
||||
function getChartData(){
|
||||
return;
|
||||
// 获取单选框选中的值
|
||||
var timeBy = $('input[name="filter[time_by]"]:checked').val();
|
||||
|
||||
// 获取日期范围值
|
||||
var daterange = $('#daterange').val();
|
||||
|
||||
// 构建查询参数
|
||||
var params = {
|
||||
'time_by': timeBy,
|
||||
'daterange': daterange
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
url: "statistics/dispatcher/chartData", //
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
data:params,
|
||||
success: function (response) {
|
||||
// 数据结构
|
||||
// response = {
|
||||
// source: [
|
||||
// ['产品销售', '2015', '2016', '2017'],
|
||||
// ['风扇', 43.3, 85.8, 93.7],
|
||||
// ...
|
||||
// ]
|
||||
// }
|
||||
|
||||
const headers = response[0];
|
||||
const units = ['元', '%', '%', '']; // 如果你有单位可以一起拼接
|
||||
|
||||
var barChart = Echarts.init(document.getElementById('bar-chart'), 'walden');
|
||||
var option = {
|
||||
legend: {},
|
||||
tooltip: {},
|
||||
dataset: {
|
||||
source: response
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
axisLabel: {
|
||||
show: true // 隐藏“系统”
|
||||
},
|
||||
axisTick: { show: false },
|
||||
axisLine: { show: false }
|
||||
},
|
||||
yAxis: {},
|
||||
series: headers.slice(1).map((title, i) => ({
|
||||
type: 'bar',
|
||||
label: {
|
||||
show: true,
|
||||
position: 'top',
|
||||
formatter: function (params) {
|
||||
const value = params.value[i + 1]; // 因为第一列是“派单员”
|
||||
const unit = units[i] || '';
|
||||
return `${value} ${unit}`; // 显示数值 + 单位
|
||||
}
|
||||
},
|
||||
itemStyle: {
|
||||
borderRadius: 4
|
||||
}
|
||||
}))
|
||||
};
|
||||
barChart.setOption(option);
|
||||
},
|
||||
error: function () {
|
||||
console.error("图表数据加载失败");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
var form = $("#chart-filter");
|
||||
var ranges = {};
|
||||
ranges[__('Today')] = [Moment().startOf('day'), Moment().endOf('day')];
|
||||
ranges[__('Yesterday')] = [Moment().subtract(1, 'days').startOf('day'), Moment().subtract(1, 'days').endOf('day')];
|
||||
ranges[__('Last 7 Days')] = [Moment().subtract(6, 'days').startOf('day'), Moment().endOf('day')];
|
||||
ranges[__('Last 30 Days')] = [Moment().subtract(29, 'days').startOf('day'), Moment().endOf('day')];
|
||||
ranges[__('This Month')] = [Moment().startOf('month'), Moment().endOf('month')];
|
||||
ranges[__('Last Month')] = [Moment().subtract(1, 'month').startOf('month'), Moment().subtract(1, 'month').endOf('month')];
|
||||
ranges[__('今年')] = [Moment().startOf('year'), Moment().endOf('year')];
|
||||
var options = {
|
||||
timePicker: false,
|
||||
autoUpdateInput: false,
|
||||
timePickerSeconds: true,
|
||||
timePicker24Hour: true,
|
||||
autoApply: true,
|
||||
locale: {
|
||||
format: 'YYYY-MM-DD',
|
||||
customRangeLabel: __("Custom Range"),
|
||||
applyLabel: __("Apply"),
|
||||
cancelLabel: __("Clear"),
|
||||
},
|
||||
ranges: ranges,
|
||||
};
|
||||
var callback = function (start, end) {
|
||||
$(this.element).val(start.format(options.locale.format) + " - " + end.format(options.locale.format));
|
||||
};
|
||||
require(['bootstrap-daterangepicker'], function () {
|
||||
$(".datetimerange", form).each(function () {
|
||||
$(this).on('apply.daterangepicker', function (ev, picker) {
|
||||
callback.call(picker, picker.startDate, picker.endDate);
|
||||
var label = picker.chosenLabel;
|
||||
$(picker.element).data('label', label).trigger("change");
|
||||
});
|
||||
$(this).on('cancel.daterangepicker', function (ev, picker) {
|
||||
$(this).val('');
|
||||
});
|
||||
$(this).daterangepicker($.extend({}, options), callback);
|
||||
});
|
||||
});
|
||||
|
||||
// 手动触发一次激活 tab 的 shown.bs.tab
|
||||
getChartData();
|
||||
// 绑定查询按钮的点击事件
|
||||
$('#filter-btn').on('click', function() {
|
||||
getChartData();
|
||||
});
|
||||
},
|
||||
|
||||
add: function () {
|
||||
Controller.api.bindevent();
|
||||
},
|
||||
edit: function () {
|
||||
Controller.api.bindevent();
|
||||
},
|
||||
|
||||
aftersales: function () {
|
||||
Controller.api.bindevent();
|
||||
},
|
||||
|
||||
api: {
|
||||
bindevent: function () {
|
||||
Form.api.bindevent($("form[role=form]"));
|
||||
}
|
||||
}
|
||||
};
|
||||
return Controller;
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user