From 02dbc1233af7b2e218ed4d395f4d96d3e8399cf5 Mon Sep 17 00:00:00 2001 From: hant Date: Sun, 22 Jun 2025 18:41:46 +0800 Subject: [PATCH] =?UTF-8?q?=E9=80=80=E5=8D=95=E7=BB=9F=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/controller/statistics/Aftersale.php | 50 ++++- application/admin/model/Order.php | 3 + .../view/statistics/aftersale/index.html | 22 ++- public/assets/js/backend/order.js | 183 ++++++++++-------- .../assets/js/backend/statistics/aftersale.js | 26 ++- 5 files changed, 194 insertions(+), 90 deletions(-) diff --git a/application/admin/controller/statistics/Aftersale.php b/application/admin/controller/statistics/Aftersale.php index 9dd9525..c2174fe 100644 --- a/application/admin/controller/statistics/Aftersale.php +++ b/application/admin/controller/statistics/Aftersale.php @@ -19,7 +19,7 @@ class Aftersale extends Backend { protected $noNeedRight = ['*']; - protected $relationSearch = true,$items,$itemsformattedTree; + protected $relationSearch = true,$items,$itemsformattedTree,$sources; public function _initialize() { @@ -42,6 +42,29 @@ class Aftersale extends Backend $this->itemsformattedTree = $formattedTree; $this->view->assign("items", $formattedTree); $this->view->assign("default_daterange", $default_daterange); + + $sources = Db::name('source') + ->where('status', 1) + ->field(['id', 'title', 'key_word', 'pid']) + ->order('pid', 'asc') + ->order('sort', 'desc') + ->select(); + $this->sources = $sources; + $filtered = array_filter($sources, function ($item) { + return $item['pid'] == 0; + }); + + $pid_map = array_column($filtered, null, 'id'); + $res = []; + foreach ($sources as $item) { + if ($item['pid'] != 0 && isset($pid_map[$item['pid']])) { + $res [] = [ + ...$item, 'ptitle' => $pid_map[$item['pid']]['title'],'name'=>$item['title'].' - '.$pid_map[$item['pid']]['title'], + ]; + } + } + $this->view->assign("sources", $res); + parent::_initialize(); } @@ -128,6 +151,7 @@ class Aftersale extends Backend $start = now()->modify('-30 days')->format('Y-m-d'); $end_at = now()->format('Y-m-d 23:29:59'); $area_code = request()->get('area_id'); + $source = request()->get('source'); $filter = request()->get('range', ''); if (!empty($filter)) { $arr = explode(' - ', $filter); @@ -140,15 +164,19 @@ class Aftersale extends Backend } $build->where('audit_time', '>=', $start); $build->where('audit_time', '<=', $end_at); - $build->group('a.area_id'); + $build->group('a.source,a.area_id'); if ($area_code) { $build->where('area_id', 'like', $this->getSelectAreaCode($area_code) . '%'); } + if ($source) { + $build->where('source', $source); + } $build->field( [ + 'a.source', 'a.area_id', 'count(a.id) order_total', 'count(c.id) after_total', @@ -157,7 +185,10 @@ class Aftersale extends Backend )->with([ 'area' => function ($q) { $q->field('id,area_code,merge_name'); - } + }, + 'source' => function ($q) { + $q->field('id,title'); + }, ]); $res = $build->paginate(); @@ -189,6 +220,7 @@ class Aftersale extends Backend $start = now()->modify('-30 days')->format('Y-m-d'); $end_at = now()->format('Y-m-d 23:29:59'); $item_id = request()->get('item_id'); + $source = request()->get('source'); $filter = request()->get('range', ''); if (!empty($filter)) { $arr = explode(' - ', $filter); @@ -201,7 +233,7 @@ class Aftersale extends Backend } $build->where('audit_time', '>=', $start); $build->where('audit_time', '<=', $end_at); - $build->group('a.item_id,a.item_title'); + $build->group('a.source,a.item_id,a.item_title'); @@ -210,16 +242,24 @@ class Aftersale extends Backend $item_ids [] = $item_id; $build->whereIn('item_id', $item_ids); } + if ($source) { + $build->where('source', $source); + } $build->field( [ + 'a.source', 'a.item_id', 'a.item_title', 'count(a.id) order_total', 'count(c.id) after_total', 'sum(c.refund_amount) refund_amount', ] - ); + )->with([ + 'source' => function ($q) { + $q->field('id,title'); + }, + ]); $res = $build->paginate(); $total = $res->total(); diff --git a/application/admin/model/Order.php b/application/admin/model/Order.php index 0aea1cd..ec81065 100644 --- a/application/admin/model/Order.php +++ b/application/admin/model/Order.php @@ -199,6 +199,9 @@ class Order extends Model public function item(){ return $this->belongsTo(Item::class,'item_id',); } + public function source(){ + return $this->belongsTo(Source::class,'source'); + } public function area(){ return $this->belongsTo(Area::class,'area_id','area_code'); diff --git a/application/admin/view/statistics/aftersale/index.html b/application/admin/view/statistics/aftersale/index.html index 91a5e3a..168d2d3 100644 --- a/application/admin/view/statistics/aftersale/index.html +++ b/application/admin/view/statistics/aftersale/index.html @@ -195,14 +195,23 @@
-
+ + +
- + placeholder="指定日期" name="filter[daterange]" id="daterange-table2" autocomplete="off" style="position: absolute;left: 475px;width: 180px;"> + +
@@ -216,6 +225,13 @@
+
diff --git a/public/assets/js/backend/order.js b/public/assets/js/backend/order.js index 8f311b3..f363218 100644 --- a/public/assets/js/backend/order.js +++ b/public/assets/js/backend/order.js @@ -28,21 +28,39 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'cascader'], function // 拼装文本 function assembleOrderMessage(data) { - const message = `订单编号: ${data.order_no} + let message = ''; + if (!data.coupon) { + message = `订单编号: ${data.order_no} 服务名称: ${data.item_title} 客户昵称: ${data.customer} 客户电话: ${data.tel} 客户地址: ${data.address} -收款金额: ${data.receive_type === 1 ? '已收定金 ' + data.online_amount : '已收全款 ' + data.online_amount} -优惠活动: ${data.coupon?.description || '无'} -订单详情: ${data.detail || '无'} -订单备注: ${data.remark} +下单金额: ${data.receive_type === 1 ? '已收定金 ' + formatNumber(data.online_amount) : '已收全款 ' + formatNumber(data.online_amount)} +订单备注: ${data.remark || '无'} 预约时间: ${data.plan_time || '无'} `; + } else { + message = `订单编号: ${data.order_no} +服务名称: ${data.item_title} +客户昵称: ${data.customer} +客户电话: ${data.tel} +客户地址: ${data.address} +下单金额: ${data.receive_type === 1 ? '已收定金 ' + formatNumber(data.online_amount) : '已收全款 ' + formatNumber(data.online_amount)} +优惠活动: ${data.coupon?.description || '无'} +订单备注: ${data.remark ||'无'} +预约时间: ${data.plan_time || '无'} +`; + } return message; } + function formatNumber(value, decimals = 1) { + let num = parseFloat(value); + if (isNaN(num)) return '0.0'.slice(0, decimals + 2); // e.g. '0.0' or '0.00' + return num.toFixed(decimals); + } + var Controller = { index: function () { @@ -83,7 +101,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'cascader'], function fixed: true, searchList: { "0": __('Status 0'), - "10": __('Status 10'), + "10": __('Status 10'), "20": __('Status 20'), "30": __('Status 30'), "40": __('Status 40'), @@ -115,7 +133,8 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'cascader'], function var now = new Date(); var diffMinutes = (now - createTime) / (1000 * 60); // 计算分钟差 - return diffMinutes > 20 ? '超时' : '未超时';; + return diffMinutes > 20 ? '超时' : '未超时'; + ; }, searchList: { "1": '超时', @@ -211,13 +230,15 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'cascader'], function autocomplete: false }, - {field: 'area_id', title: __('地区'), searchList: function (column) { + { + field: 'area_id', title: __('地区'), searchList: function (column) { return Template('categorytpl', {}); }, formatter: function (value, row, index) { return '无'; }, visible: false }, - {field: 'item_id', title: '服务项目', searchList: function (column) { + { + field: 'item_id', title: '服务项目', searchList: function (column) { return Template('items_picker', {}); }, formatter: function (value, row, index) { return '无'; @@ -470,7 +491,6 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'cascader'], function resetIdleTimer(); - var _data = items; $('#select_item').zdCascader({ data: _data, @@ -478,7 +498,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'cascader'], function // console.log(data,allPathData); $('#select_item_id').val(data.value); }, - clear:true, + clear: true, clickParent: true }); @@ -486,14 +506,14 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'cascader'], function add: function () { $("#mybuttom").on("click", function () { const res = $("form[role=form]").isValid(); - if ($('#lng').val() && $('#lng').val() !== ''){ + if ($('#lng').val() && $('#lng').val() !== '') { if (res) { - Form.api.submit($("form[role=form]"),function (data){ + Form.api.submit($("form[role=form]"), function (data) { copyToClipboard(assembleOrderMessage(data)); }); } - }else{ + } else { Toastr.success('请选择有效地址'); } @@ -503,7 +523,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'cascader'], function $("#mysubmit").on("click", function () { const res = $("form[role=form]").isValid(); - if ($('#lng').val() && $('#lng').val() !== ''){ + if ($('#lng').val() && $('#lng').val() !== '') { if (res) { Form.api.submit($("form[role=form]"), function (data, ret) { clearInfo(); @@ -511,7 +531,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'cascader'], function return false; }); } - }else{ + } else { Toastr.success('请选择有效地址'); } return false; @@ -519,54 +539,54 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'cascader'], function $("#smart").on("click", function () { Fast.api.ajax({ - url: "order/smart", // 你的 API 地址 - type: "post", - contentType: 'application/json', - dataType: "json", - data: JSON.stringify({ - str: $('#smart_text').val() - }) - }, function (data) { - if (data.mobile !== '') { - $('#c-tel').val(data.mobile); - } - if (data.name !== '') { - $('#c-customer').val(data.name); - } - if (data.item.id !== 0) { - $('#item_id_value').val(data.item.id); - $('#item_id').val(data.item.item); - } - if (data.idn) { - $('#c-source-id').val(data.idn); - } - // $city.citypicker({ - // province: data.province, - // city: data.city, - // district: data.region - // }); - if (data.area_id) { - $("#area_id").val(data.area_id); - } - if (data.lat) { - $("#lat").val(data.lat); - } - if (data.lng) { - $("#lng").val(data.lng); - } - if (data.area_id) { - $("#area_id").val(data.area_id); - } - if (data.plan_time) { - $("#time").val(data.plan_time); - } - if (data.addr && data.addr !== '') { - $("#c-address").val(data.addr); - $("#area_name").val(data.addr); - } - Toastr.info('识别成功'); - return false; - }); + url: "order/smart", // 你的 API 地址 + type: "post", + contentType: 'application/json', + dataType: "json", + data: JSON.stringify({ + str: $('#smart_text').val() + }) + }, function (data) { + if (data.mobile !== '') { + $('#c-tel').val(data.mobile); + } + if (data.name !== '') { + $('#c-customer').val(data.name); + } + if (data.item.id !== 0) { + $('#item_id_value').val(data.item.id); + $('#item_id').val(data.item.item); + } + if (data.idn) { + $('#c-source-id').val(data.idn); + } + // $city.citypicker({ + // province: data.province, + // city: data.city, + // district: data.region + // }); + if (data.area_id) { + $("#area_id").val(data.area_id); + } + if (data.lat) { + $("#lat").val(data.lat); + } + if (data.lng) { + $("#lng").val(data.lng); + } + if (data.area_id) { + $("#area_id").val(data.area_id); + } + if (data.plan_time) { + $("#time").val(data.plan_time); + } + if (data.addr && data.addr !== '') { + $("#c-address").val(data.addr); + $("#area_name").val(data.addr); + } + Toastr.info('识别成功'); + return false; + }); }); Controller.api.bindevent(); Controller.api.map(); @@ -739,26 +759,27 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'cascader'], function $('#suggestionList').show(); }) .on('keydown', function (e) { - const $items = $('#suggestionList li'); - const len = $items.length; + const $items = $('#suggestionList li'); + const len = $items.length; - if (!len) return; + if (!len) return; - if (e.key === 'ArrowDown') { - e.preventDefault(); - selectedIndex = (selectedIndex + 1) % len; - updateActiveItem($items); - } else if (e.key === 'ArrowUp') { - e.preventDefault(); - selectedIndex = (selectedIndex - 1 + len) % len; - updateActiveItem($items); - } else if (e.key === 'Enter') { - if (selectedIndex >= 0 && selectedIndex < len) { + if (e.key === 'ArrowDown') { e.preventDefault(); - $items.eq(selectedIndex).trigger('mousedown'); + selectedIndex = (selectedIndex + 1) % len; + updateActiveItem($items); + } else if (e.key === 'ArrowUp') { + e.preventDefault(); + selectedIndex = (selectedIndex - 1 + len) % len; + updateActiveItem($items); + } else if (e.key === 'Enter') { + if (selectedIndex >= 0 && selectedIndex < len) { + e.preventDefault(); + $items.eq(selectedIndex).trigger('mousedown'); + } } - } - }); + }); + function updateActiveItem($items) { $items.removeClass('active'); if (selectedIndex >= 0) { @@ -836,7 +857,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'cascader'], function addressSelected = true; }); - function choseFirst(){ + function choseFirst() { const first = $('#suggestionList li').first(); const name = first.data('name'); const location = first.data('location'); // "经度,纬度" diff --git a/public/assets/js/backend/statistics/aftersale.js b/public/assets/js/backend/statistics/aftersale.js index ee35774..6fbc7af 100644 --- a/public/assets/js/backend/statistics/aftersale.js +++ b/public/assets/js/backend/statistics/aftersale.js @@ -48,12 +48,30 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template', 'addtabs' e.preventDefault(); const range = $('#daterange-table2').val(); const area_id = $('#area_id').val(); + const source = $('#table2-source').val(); let data = ''; if (range !== ''){ data += 'range=' + range; } if (area_id !== ''){ - data += 'area_id=' + area_id; + data += '&area_id=' + area_id; + } + if (source !== ''){ + data += '&source=' + source; + } + // data = encodeURIComponent(data); + $("#table2").bootstrapTable('refresh',{ + url:'statistics/aftersale/city?' + data, + }); + }); + $('#reset2').on('click', function (e) { + $("#city-search").citypicker('reset'); + $("#area_id").val(''); + $('#table2-source option:first').prop('selected', true); + const range = $('#daterange-table2').val(); + let data = ''; + if (range !== ''){ + data += 'range=' + range; } // data = encodeURIComponent(data); $("#table2").bootstrapTable('refresh',{ @@ -65,6 +83,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template', 'addtabs' const range = $('#daterange-table3').val(); const item_id = $('#item_id_value').val(); + const source = $('#table3-source').val(); let data = ''; if (range !== ''){ data += 'range=' + range; @@ -72,6 +91,9 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template', 'addtabs' if (item_id !== ''){ data += '&item_id=' + item_id; } + if (source !== ''){ + data += '&source=' + source; + } // data = encodeURIComponent(data); $("#table3").bootstrapTable('refresh',{ url:'statistics/aftersale/item?' + data, @@ -156,6 +178,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template', 'addtabs' searchFormVisible: true, columns: [ [ + {field: 'source.title', title: '渠道', operate: false}, {field: 'area.merge_name', title: '城市', operate: false}, {field: 'order_total', title: '订单总数', operate: false}, {field: 'after_total', title: '退款订单数', operate: false}, @@ -205,6 +228,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template', 'addtabs' searchFormVisible: true, columns: [ [ + {field: 'source.title', title: '渠道', operate: false}, {field: 'item_title', title: '服务项目', operate: false}, {field: 'order_total', title: '订单总数', operate: false}, {field: 'refund_amount', title: '退款金额', operate: false},