From 76cfa6b27807c9b44e833a65155ec8df29bf9a75 Mon Sep 17 00:00:00 2001
From: gitfjn <2860488097@qq.com>
Date: Fri, 30 Jan 2026 18:48:13 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=86=85=E5=AE=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../admin/controller/BulletinBoard.php | 247 ++++++++++++++
application/admin/controller/Order.php | 54 ++--
application/admin/controller/Staff.php | 7 +
application/admin/logic/GoodsLogic.php | 3 +-
application/admin/logic/OrderLogic.php | 14 +-
application/admin/logic/OrderautoLogic.php | 10 +-
application/admin/logic/StaffLogic.php | 41 +++
.../admin/view/bulletin_board/index.html | 303 +++++++++---------
application/admin/view/order/eidt.html | 149 ++++++++-
application/admin/view/order/lists.html | 86 ++++-
application/admin/view/staff/wages.html | 8 +-
application/api/controller/Order.php | 6 +-
application/api/controller/Points.php | 45 ++-
application/api/controller/Share.php | 2 +-
application/api/logic/GoodsLogic.php | 2 +-
application/api/logic/OrderLogic.php | 48 +--
application/api/logic/PointsLogic.php | 102 ++++--
application/api/model/Goods.php | 13 +
application/api/model/GoodsPoints.php | 10 +
application/api/model/OrderPoints.php | 24 ++
application/api/model/UserAddress.php | 10 +
application/common/logic/OrderRefundLogic.php | 4 +-
application/common/logic/PayNotifyLogic.php | 36 +--
application/common/model/Ad.php | 6 +-
.../common/server/storage/engine/Aliyun.php | 2 +-
25 files changed, 943 insertions(+), 289 deletions(-)
create mode 100644 application/api/model/GoodsPoints.php
create mode 100644 application/api/model/OrderPoints.php
create mode 100644 application/api/model/UserAddress.php
diff --git a/application/admin/controller/BulletinBoard.php b/application/admin/controller/BulletinBoard.php
index bf70c2af..62719ebe 100644
--- a/application/admin/controller/BulletinBoard.php
+++ b/application/admin/controller/BulletinBoard.php
@@ -6,6 +6,7 @@ use app\admin\model\OrderRecharge;
use app\admin\model\OrderYearcard;
use app\admin\model\User;
use app\common\server\UrlServer;
+use think\Db;
use think\facade\Url;
use app\admin\model\Order;
@@ -15,6 +16,14 @@ class BulletinBoard extends AdminBase
//看板统计
public function index()
{
+ // 本月与上月时间范围
+ $monthStart = date('Y-m-01 00:00:00');
+ $monthEnd = date('Y-m-t 23:59:59');
+ $lastMonthStart = date('Y-m-01 00:00:00', strtotime('-1 month'));
+ $lastMonthEnd = date('Y-m-t 23:59:59', strtotime('-1 month'));
+ $monthStartTs = strtotime($monthStart);
+ $monthEndTs = strtotime($monthEnd);
+
//查询商品订单
$orderMoney = Order::where('status','<>', 0)->sum('order_amount');
//年卡订单
@@ -104,6 +113,243 @@ class BulletinBoard extends AdminBase
// 本月注册但没下过单的(新客户)
$newCustomerCount = count($monthUsers) - $oldCustomerCount;
}
+
+ // ========== 目标完成率与客服进度 ==========
+ // 销售目标(可以后续做成后台可配置,这里先写死为 100000)
+ $monthlyTarget = 100000;
+ $overallCompletion = $monthlyTarget > 0 ? round(($monthlySales / $monthlyTarget) * 100, 2) : 0;
+
+ // 按客服统计本月与上月销售额
+ $staffCurrent = Db::name('order')
+ ->alias('o')
+ ->join('admin a', 'o.admin_id = a.id', 'LEFT')
+ ->where('o.status', '<>', 0)
+ ->whereTime('o.create_time', 'between', [$monthStart, $monthEnd])
+ ->field('o.admin_id,a.name as staff_name,SUM(o.order_amount) as total')
+ ->group('o.admin_id')
+ ->select();
+
+ $staffLast = Db::name('order')
+ ->alias('o')
+ ->join('admin a', 'o.admin_id = a.id', 'LEFT')
+ ->where('o.status', '<>', 0)
+ ->whereTime('o.create_time', 'between', [$lastMonthStart, $lastMonthEnd])
+ ->field('o.admin_id,SUM(o.order_amount) as total')
+ ->group('o.admin_id')
+ ->select();
+
+ $staffLastMap = [];
+ foreach ($staffLast as $row) {
+ $staffLastMap[$row['admin_id']] = $row['total'];
+ }
+
+ $staffProgress = [];
+ foreach ($staffCurrent as $row) {
+ $adminId = $row['admin_id'];
+ $staffSales = (float)$row['total'];
+ $lastSales = isset($staffLastMap[$adminId]) ? (float)$staffLastMap[$adminId] : 0;
+ $percent = $monthlySales > 0 ? round(($staffSales / $monthlySales) * 100, 2) : 0;
+ $yoy = $lastSales > 0 ? round((($staffSales - $lastSales) / $lastSales) * 100, 2) : 0;
+
+ $staffProgress[] = [
+ 'name' => $row['staff_name'] ?: '未分配',
+ 'sales' => $staffSales,
+ 'percent' => $percent,
+ 'yoy' => $yoy,
+ ];
+ }
+
+ // ========== 渠道分析(当月订单数按渠道) ==========
+ $channelRows = Db::name('order')
+ ->alias('o')
+ ->join('orderchannel c', 'o.channel_id = c.id', 'LEFT')
+ ->where('o.status', '<>', 0)
+ ->whereTime('o.create_time', 'month')
+ ->field('c.name as channel_name, COUNT(*) as total')
+ ->group('o.channel_id')
+ ->select();
+
+ $channelPie = [];
+ foreach ($channelRows as $row) {
+ $name = $row['channel_name'] ?: '其他';
+ $value = (int)$row['total'];
+ $channelPie[] = [
+ 'name' => $name,
+ 'value' => $value,
+ ];
+ }
+
+ // ========== 每日销售趋势(仅商品订单,按天汇总) ==========
+ $trendRows = Db::name('order')
+ ->where('status', '<>', 0)
+ ->whereTime('create_time', 'between', [$monthStart, $monthEnd])
+ ->field("FROM_UNIXTIME(create_time,'%Y-%m-%d') as day, SUM(order_amount) as total")
+ ->group('day')
+ ->order('day asc')
+ ->select();
+
+ $trendDates = [];
+ $trendValues = [];
+ $trendTotal = 0;
+ foreach ($trendRows as $row) {
+ $trendDates[] = $row['day'];
+ $amount = (float)$row['total'];
+ $trendValues[] = $amount;
+ $trendTotal += $amount;
+ }
+
+ // 上月总销售额(用于计算趋势图上的“上月同比”)
+ $lastTrendTotal = Db::name('order')
+ ->where('status', '<>', 0)
+ ->whereTime('create_time', 'between', [$lastMonthStart, $lastMonthEnd])
+ ->sum('order_amount');
+
+ $trendCompare = $lastTrendTotal > 0 ? round((($trendTotal - $lastTrendTotal) / $lastTrendTotal) * 100, 2) : 0;
+
+ // ========== 区域月销售额(通过地址模糊匹配简单统计) ==========
+ $regions = ['南明区', '云岩区', '白云区', '乌当区', '花溪区', '龙里'];
+ $regionTotals = [];
+ foreach ($regions as $regionName) {
+ $total = Db::name('order')
+ ->where('status', '<>', 0)
+ ->whereTime('create_time', 'month')
+ ->whereLike('address', '%' . $regionName . '%')
+ ->sum('order_amount');
+ $regionTotals[] = (float)$total;
+ }
+
+ // ========== 本月销售情况(单次/年卡/次卡/其它服务) ==========
+ // 复用统计图表控制器中的规则:根据 number 字段区分不同卡类型
+ $salesSituation = [
+ ['value' => 0, 'name' => '单次服务'],
+ ['value' => 0, 'name' => '年卡销量'],
+ ['value' => 0, 'name' => '次卡销量'],
+ ['value' => 0, 'name' => '其它服务'],
+ ];
+ $kaWhere = [
+ ['del', '=', 0],
+ ['create_time', '>=', $monthStartTs],
+ ['create_time', '<=', $monthEndTs],
+ ];
+ // 单次服务:number = 1
+ $salesSituation[0]['value'] = Db::name('order')
+ ->where($kaWhere)
+ ->where('number', '=', 1)
+ ->sum('total_amount');
+ // 年卡:number > 6
+ $salesSituation[1]['value'] = Db::name('order')
+ ->where($kaWhere)
+ ->where('number', '>', 6)
+ ->sum('total_amount');
+ // 次卡:2 <= number <= 6
+ $salesSituation[2]['value'] = Db::name('order')
+ ->where($kaWhere)
+ ->where('number', '>=', 2)
+ ->where('number', '<=', 6)
+ ->sum('total_amount');
+ // 其它服务:number = 0
+ $salesSituation[3]['value'] = Db::name('order')
+ ->where($kaWhere)
+ ->where('number', '=', 0)
+ ->sum('total_amount');
+
+ // ========== 渠道 & 区域详细拆分(总额 / 年卡 / 次卡 / 单次 / 其它) ==========
+ $serviceTypes = [
+ 'total' => [],
+ 'year' => [['number', '>', 6]],
+ 'times' => [['number', '>=', 2], ['number', '<=', 6]],
+ 'single'=> [['number', '=', 1]],
+ 'other' => [['number', '=', 0]],
+ ];
+
+ // 渠道关键字到列 key 的映射
+ $channelBuckets = [
+ 'meituan' => '美团',
+ 'gzh' => '公众号',
+ 'douyin' => '抖音',
+ 'staff' => '员工',
+ 'yeye' => '异业',
+ 'other' => '渠道',
+ ];
+
+ $channelDetail = [];
+ foreach ($serviceTypes as $typeKey => $extraWhere) {
+ $totals = [
+ 'meituan' => 0,
+ 'gzh' => 0,
+ 'douyin' => 0,
+ 'staff' => 0,
+ 'yeye' => 0,
+ 'other' => 0,
+ ];
+
+ $query = Db::name('order')
+ ->alias('o')
+ ->join('orderchannel c', 'o.channel_id = c.id', 'LEFT')
+ ->where('o.status', '<>', 0)
+ ->whereBetween('o.create_time', [$monthStartTs, $monthEndTs]);
+
+ if (!empty($extraWhere)) {
+ $query->where($extraWhere);
+ }
+
+ $rows = $query
+ ->field('c.name as channel_name, SUM(o.order_amount) as total')
+ ->group('o.channel_id')
+ ->select();
+
+ foreach ($rows as $row) {
+ $name = $row['channel_name'] ?? '';
+ $value = (float)($row['total'] ?? 0);
+ $bucket = 'other';
+ if (mb_strpos($name, '美团') !== false) {
+ $bucket = 'meituan';
+ } elseif (mb_strpos($name, '公众号') !== false || mb_strpos($name, '公') !== false) {
+ $bucket = 'gzh';
+ } elseif (mb_strpos($name, '抖音') !== false) {
+ $bucket = 'douyin';
+ } elseif (mb_strpos($name, '员工') !== false) {
+ $bucket = 'staff';
+ } elseif (mb_strpos($name, '异业') !== false) {
+ $bucket = 'yeye';
+ }
+ $totals[$bucket] += $value;
+ }
+
+ $channelDetail[$typeKey] = $totals;
+ }
+
+ // 区域明细:每种服务类型在各区域的销售额
+ $regionDetail = [];
+ foreach ($serviceTypes as $typeKey => $extraWhere) {
+ $regionDetail[$typeKey] = [];
+ foreach ($regions as $regionName) {
+ $q = Db::name('order')
+ ->where('status', '<>', 0)
+ ->whereBetween('create_time', [$monthStartTs, $monthEndTs])
+ ->whereLike('address', '%' . $regionName . '%');
+ if (!empty($extraWhere)) {
+ $q->where($extraWhere);
+ }
+ $regionDetail[$typeKey][$regionName] = (float)$q->sum('order_amount');
+ }
+ }
+
+ // 汇总仪表盘数据供前端使用
+ $dashboardData = [
+ 'monthlyTarget' => $monthlyTarget,
+ 'overallCompletion' => $overallCompletion,
+ 'staffProgress' => $staffProgress,
+ 'channelPie' => $channelPie,
+ 'trendDates' => $trendDates,
+ 'trendValues' => $trendValues,
+ 'trendCompare' => $trendCompare,
+ 'regions' => $regions,
+ 'regionTotals' => $regionTotals,
+ 'salesSituation' => $salesSituation,
+ 'channelDetail' => $channelDetail,
+ 'regionDetail' => $regionDetail,
+ ];
// 传递数据到视图
$this->assign([
@@ -115,6 +361,7 @@ class BulletinBoard extends AdminBase
'customersCompare' => $customersCompare,
'oldCustomers' => $oldCustomerCount, // 老客户数量(本月注册且下过单的)
'newCustomers' => $newCustomerCount, // 新客户数量(本月注册但没下过单的)
+ 'dashboardData' => json_encode($dashboardData, JSON_UNESCAPED_UNICODE),
]);
return $this->fetch();
diff --git a/application/admin/controller/Order.php b/application/admin/controller/Order.php
index 0c887287..ea427adf 100644
--- a/application/admin/controller/Order.php
+++ b/application/admin/controller/Order.php
@@ -100,26 +100,42 @@ class Order extends AdminBase
*/
public function del()
{
-
if ($this->request->isAjax()) {
- dump(123);die;
- // $post = $this->request->post('');
- // $order=Db::name('order')->where('id',$post['order_id'])->find();//查询订单信息
-
- // if($this->admin_id!=6){
- // $this->_error('无权限删除');
- // }else{
- // $orderdel=Db::name('order_exe')->where('order_sn',$order['order_sn'])->find();
- // if($orderdel){
- // $this->_error('无法删除,存在主订单');
- // }else{
- // $del=Db::name('order')->where('id',$post['order_id'])->delete();
- // $this->_success('删除成功');
- // }
-
- // }
-
+ $id = $this->request->get('id');
+ $order = Db::name('order')->find($id);//查询订单信息
+ if ($order == null){
+ $this->_error('订单不存在');
+ }
+ $del = Db::name('order')->where('id',$id)->update(['del' => 1]);
+ if($del){
+ $this->_success('删除成功');
+ }else{
+ $this->_error('删除失败');
+ }
+ }
+ }
+ /**
+ * User: 恢复已删除订单
+ * Desc: 将 del 从 1 恢复为 0
+ */
+ public function recover()
+ {
+ if ($this->request->isAjax()) {
+ $id = $this->request->get('id');
+ $order = Db::name('order')->find($id);// 查询订单信息
+ if ($order == null){
+ $this->_error('订单不存在');
+ }
+ if ($order['del'] == 0) {
+ $this->_error('订单未删除,无需恢复');
+ }
+ $res = Db::name('order')->where('id',$id)->update(['del' => 0]);
+ if ($res) {
+ $this->_success('恢复成功');
+ } else {
+ $this->_error('恢复失败');
+ }
}
}
@@ -268,7 +284,7 @@ class Order extends AdminBase
$this->_success('修改订单成功', OrderLogic::edit($post));
}
- $this->assign('info', json_encode(OrderLogic::orderinfoid($id), JSON_UNESCAPED_UNICODE));
+ $this->assign('info', json_encode(OrderLogic::orderinfoid($id), JSON_UNESCAPED_UNICODE));
$brand_lists=Db::name('orderchannel')->select();
$this->assign('brand_lists', json_encode($brand_lists, JSON_UNESCAPED_UNICODE));
$this->assign('category_lists', json_encode(StaffLogic::getAllTree(), JSON_UNESCAPED_UNICODE));
diff --git a/application/admin/controller/Staff.php b/application/admin/controller/Staff.php
index 433ac8f7..2f6a5a50 100644
--- a/application/admin/controller/Staff.php
+++ b/application/admin/controller/Staff.php
@@ -659,6 +659,13 @@ public function group_del(){
$this->assign('goods_brand',StaffLogic::goods_brand());
return $this->fetch();
}
+
+ // 员工工资导出
+ public function exportWages()
+ {
+ $get = $this->request->get();
+ $this->_success('', StaffLogic::wagesExport($get));
+ }
//删除员工的工资
public function wagesdel(){
diff --git a/application/admin/logic/GoodsLogic.php b/application/admin/logic/GoodsLogic.php
index cf6c6c16..425e5da7 100644
--- a/application/admin/logic/GoodsLogic.php
+++ b/application/admin/logic/GoodsLogic.php
@@ -291,7 +291,8 @@ class GoodsLogic
'give_integral_type' => $give_integral_type,
'give_integral' => $give_integral,
'spec_type' => $post['spec_type'],
- 'create_time' => $time
+ 'create_time' => $time,
+ 'type' => $post['type']
];
$goods_id = Db::name('goods')->insertGetId($data);
diff --git a/application/admin/logic/OrderLogic.php b/application/admin/logic/OrderLogic.php
index 435a73f1..0eb413b7 100644
--- a/application/admin/logic/OrderLogic.php
+++ b/application/admin/logic/OrderLogic.php
@@ -34,10 +34,14 @@ class OrderLogic
public static function getListsCondition($get)
{
$where = [];
-
- //订单状态
- if ($get['type'] != '') {
- $where[] = ['pay_status', '=', $get['type']];
+ if ($get['type'] != 66){
+ //订单状态
+ if ($get['type'] != '') {
+ $where[] = ['pay_status', '=', $get['type']];
+ }
+ $where[] = ['del', '=', 0];
+ }else{
+ $where[] = ['del', '=', 1];
}
//订单编号查询
if (isset($get['order_sn']) && $get['order_sn'] != '') {
@@ -117,7 +121,7 @@ class OrderLogic
$order = new Order();
$where = self::getListsCondition($get);
$field = 'o.*,order_status as order_status_text,pay_way as pay_way_text';
- $brand = Db::name('goods_brand')->where(['del' => 0])->column('name', 'id'); //订单类型
+ $brand = Db::name('goods_brand')->column('name', 'id'); //订单类型
$admin = Db::name('admin')->column('name', 'id');
$count = $order
->where($where)
diff --git a/application/admin/logic/OrderautoLogic.php b/application/admin/logic/OrderautoLogic.php
index e4f7859a..ed25d5d5 100644
--- a/application/admin/logic/OrderautoLogic.php
+++ b/application/admin/logic/OrderautoLogic.php
@@ -14,7 +14,9 @@ class OrderautoLogic{
public static function lists($get){
$where = [];
//判断已经支付的订单
- $where[] = ['pay_status', '=', 1];
+// $where[] = ['pay_status', '=', 1];
+ $where[] = ['refund_status', '=', 0];
+ $where[] = ['del', '=', 0];
if(isset($get['type']) && $get['type'] != ''){
$where[] = ['static','=',$get['type']];
}
@@ -38,10 +40,8 @@ class OrderautoLogic{
$where[] = ['status','=',$get['status']];
}
- // 执行状态查询
- if(isset($get['admin']) && $get['admin']!= ''){
- $where[] = ['admin_id','=',$get['admin']];
- }
+ // 如果订单的admin_id不等于空,不需要限制支付状态;如果admin_id等于空,只查询已支付的订单
+ $where[] = ['', 'exp', Db::raw("(admin_id IS NOT NULL AND admin_id != '') OR pay_status = 1")];
// 订单的来源查询
if(isset($get['pid']) && $get['pid']!= ''){
$where[] = ['channel_id','=',$get['pid']];
diff --git a/application/admin/logic/StaffLogic.php b/application/admin/logic/StaffLogic.php
index 0aa8b68d..e14a37a3 100644
--- a/application/admin/logic/StaffLogic.php
+++ b/application/admin/logic/StaffLogic.php
@@ -624,6 +624,47 @@ class StaffLogic{
public static function adder($post){
return Db::name('staff')->where('id',$post['id'])->update(['lng'=>$post['store_longitude'],'lat'=>$post['store_latitude']]);
}
+
+ // 员工工资导出数据(基于 wages 列表结果,避免重复重算导致超时)
+ public static function wagesExport($get)
+ {
+ // 导出时最多导出 5000 条,且沿用 wages 的统计逻辑
+ $get['page'] = 1;
+ $get['limit'] = isset($get['limit']) && (int)$get['limit'] > 0 ? (int)$get['limit'] : 5000;
+
+ $data = self::wages($get);
+ $lists = $data['lists'] ?? [];
+
+ // 组装导出数据
+ $exportTitle = ['员工姓名', '员工电话', '服务总订单', '上午订单', '下午订单', '财务报销', '上午加时', '下午加时', '请假天数', '出勤天数', '罚款金额', '异常订单', '年卡订单', '物料金额'];
+ $exportData = [];
+ foreach ($lists as $row) {
+ $exportData[] = [
+ $row['name'] ?? '',
+ $row['mobile'] ?? '',
+ $row['total_orders'] ?? 0,
+ $row['sw_orders'] ?? 0,
+ $row['xw_orders'] ?? 0,
+ $row['finance'] ?? 0,
+ $row['sw_addtimes'] ?? 0,
+ $row['xw_addtimes'] ?? 0,
+ $row['leaves'] ?? 0,
+ $row['attendance'] ?? 0,
+ $row['fine'] ?? 0,
+ $row['abnormal'] ?? 0,
+ $row['annual'] ?? 0,
+ $row['erp_staff'] ?? 0,
+ ];
+ }
+
+ $exportExt = 'xls';
+ return [
+ 'exportTitle' => $exportTitle,
+ 'exportData' => $exportData,
+ 'exportExt' => $exportExt,
+ 'exportName' => '员工工资-' . date('Y-m-d H:i:s'),
+ ];
+ }
//获取员工积分记录
public static function points($get){
diff --git a/application/admin/view/bulletin_board/index.html b/application/admin/view/bulletin_board/index.html
index 3daf8b21..33ae0518 100644
--- a/application/admin/view/bulletin_board/index.html
+++ b/application/admin/view/bulletin_board/index.html
@@ -200,57 +200,24 @@
当月目标完成率
-
本月销售目标: 10万
+
+ 本月销售目标:
+ --
+
客服目标完成率(N个客服的目标陈列)
-
-
-
- 啦啦
- 销售额: XXX | 百分比: xx% | 同比: xx%
-
-
-
-
-
- 小喵
- 销售额: XXX | 百分比: xx% | 同比: xx%
-
-
-
-
-
- 哆哆
- 销售额: XXX | 百分比: xx% | 同比: xx%
-
-
-
-
-
- 大猫
- 销售额: XXX | 百分比: xx% | 同比: xx%
-
-
-
+
@@ -263,8 +230,8 @@
每日销售趋势
-
@@ -296,52 +263,8 @@
渠道 |
-
-
- | 总额 |
- - |
- - |
- - |
- - |
- - |
- - |
-
-
- | 年卡 |
- - |
- - |
- - |
- - |
- - |
- - |
-
-
- | 次卡 |
- - |
- - |
- - |
- - |
- - |
- - |
-
-
- | 单次服务 |
- - |
- - |
- - |
- - |
- - |
- - |
-
-
- | 其他服务 |
- - |
- - |
- - |
- - |
- - |
- - |
-
+
+
@@ -365,52 +288,8 @@
龙里 |
-
-
- | 总额 |
- - |
- - |
- - |
- - |
- - |
- - |
-
-
- | 年卡 |
- - |
- - |
- - |
- - |
- - |
- - |
-
-
- | 次卡 |
- - |
- - |
- - |
- - |
- - |
- - |
-
-
- | 单次服务 |
- - |
- - |
- - |
- - |
- - |
- - |
-
-
- | 其他服务 |
- - |
- - |
- - |
- - |
- - |
- - |
-
+
+
@@ -441,6 +320,10 @@ layui.config({
newCustomers: parseInt('{$newCustomers|default=0}') || 0
};
+ // 仪表盘其它统计数据(目标、客服进度、渠道、趋势、区域等)
+ // 这里直接输出后端已经 json_encode 好的字符串,避免模板语法冲突
+ var dashboardData = {$dashboardData|raw} || {};
+
// 渲染统计数据
renderStatistics();
@@ -451,8 +334,13 @@ layui.config({
format: 'yyyy-MM-dd'
});
- // 初始化所有图表(仅样式,不填充数据)
+ // 初始化所有图表(使用数据库数据渲染)
initCharts();
+
+ // 渲染目标完成率和客服进度条
+ renderTargetsAndStaff();
+ // 渲染渠道与区域明细表格
+ renderChannelAndRegionTables();
// 渲染统计数据
function renderStatistics() {
@@ -486,6 +374,99 @@ layui.config({
$('#customers-compare').html(formatCompare(statisticsData.customersCompare));
}
+ // 渲染销售目标、总体完成率和客服进度条
+ function renderTargetsAndStaff() {
+ if (!dashboardData) {
+ return;
+ }
+
+ // 销售目标与总体完成率
+ var target = dashboardData.monthlyTarget || 0;
+ var completion = dashboardData.overallCompletion || 0;
+
+ $('#monthly-target-text').text(target > 0 ? (target / 10000).toFixed(2) + ' 万' : '--');
+ $('#overall-completion-text').text(completion.toFixed ? completion.toFixed(2) + '%' : (completion + '%'));
+ $('#overall-completion-bar').css('width', (completion > 100 ? 100 : completion) + '%');
+
+ // 客服进度条
+ var list = $('#staff-progress-list');
+ list.empty();
+ if (dashboardData.staffProgress && dashboardData.staffProgress.length) {
+ dashboardData.staffProgress.forEach(function (item) {
+ var percentText = (item.percent || 0).toFixed(2) + '%';
+ var yoy = item.yoy || 0;
+ var yoyHtml;
+ if (yoy > 0) {
+ yoyHtml = '同比: ↑ ' + yoy.toFixed(2) + '%';
+ } else if (yoy < 0) {
+ yoyHtml = '同比: ↓ ' + Math.abs(yoy).toFixed(2) + '%';
+ } else {
+ yoyHtml = '同比: 持平';
+ }
+ var html = ''
+ + ''
+ + '
'
+ + ' ' + (item.name || '未分配') + ''
+ + ' 销售额: ' + (item.sales || 0) + ' | 百分比: ' + percentText + ' | ' + yoyHtml + ''
+ + '
'
+ + '
'
+ + '
';
+ list.append(html);
+ });
+ } else {
+ list.append('暂无客服统计数据
');
+ }
+ }
+
+ // 渠道&区域月销售明细表格渲染(只处理“总额”这一行)
+ function renderChannelAndRegionTables() {
+ if (!dashboardData) {
+ return;
+ }
+
+ // ===== 渠道月销售详情(总额 / 年卡 / 次卡 / 单次 / 其它) =====
+ var channelBody = $('#channel-month-table-body');
+ channelBody.empty();
+ var channelHeaders = ['美团','公众号','抖音','员工','异业','渠道'];
+ var rowLabels = [
+ {key: 'total', text: '总额'},
+ {key: 'year', text: '年卡'},
+ {key: 'times', text: '次卡'},
+ {key: 'single',text: '单次服务'},
+ {key: 'other', text: '其他服务'}
+ ];
+ var keyToCol = ['meituan','gzh','douyin','staff','yeye','other'];
+ rowLabels.forEach(function (row) {
+ var data = (dashboardData.channelDetail && dashboardData.channelDetail[row.key]) || {};
+ var tr = '| ' + row.text + ' | ';
+ keyToCol.forEach(function (colKey) {
+ var v = parseFloat(data[colKey] || 0).toFixed(2);
+ tr += '' + v + ' | ';
+ });
+ tr += '
';
+ channelBody.append(tr);
+ });
+
+ // ===== 区域月销售详情(总额 / 年卡 / 次卡 / 单次 / 其它) =====
+ var regionBody = $('#region-month-table-body');
+ regionBody.empty();
+ if (dashboardData.regions && dashboardData.regions.length) {
+ var regionNames = dashboardData.regions;
+ rowLabels.forEach(function (row) {
+ var rowData = (dashboardData.regionDetail && dashboardData.regionDetail[row.key]) || {};
+ var tr2 = '| ' + row.text + ' | ';
+ regionNames.forEach(function (rName) {
+ var val = parseFloat(rowData[rName] || 0).toFixed(2);
+ tr2 += '' + val + ' | ';
+ });
+ tr2 += '
';
+ regionBody.append(tr2);
+ });
+ }
+ }
+
function initCharts() {
// 月客户分析 - 饼图
var customerChart = echarts.init(document.getElementById('customer-analysis-chart'));
@@ -519,7 +500,7 @@ layui.config({
}]
});
- // 月销售情况 - 饼图
+ // 月销售情况 - 饼图(使用数据库汇总结果)
var salesChart = echarts.init(document.getElementById('sales-situation-chart'));
salesChart.setOption({
tooltip: {
@@ -544,16 +525,18 @@ layui.config({
show: true,
formatter: '{b}: {c}'
},
- data: [
- {value: 8.2, name: '年卡销售', itemStyle: {color: '#4A70F4'}},
- {value: 3.2, name: '次卡销售', itemStyle: {color: '#6DD047'}},
- {value: 1.4, name: '单次服务', itemStyle: {color: '#F6A23F'}},
- {value: 1.2, name: '其他服务', itemStyle: {color: '#87CEEB'}}
- ]
+ data: (dashboardData.salesSituation && dashboardData.salesSituation.length)
+ ? dashboardData.salesSituation
+ : [
+ {value: 0, name: '单次服务', itemStyle: {color: '#F6A23F'}},
+ {value: 0, name: '年卡销量', itemStyle: {color: '#4A70F4'}},
+ {value: 0, name: '次卡销量', itemStyle: {color: '#6DD047'}},
+ {value: 0, name: '其它服务', itemStyle: {color: '#87CEEB'}}
+ ]
}]
});
- // 当月客户渠道分析 - 环形图
+ // 当月客户渠道分析 - 环形图(使用数据库统计的渠道订单数)
var channelChart = echarts.init(document.getElementById('channel-analysis-chart'));
channelChart.setOption({
tooltip: {
@@ -578,19 +561,13 @@ layui.config({
show: true,
formatter: '{b}: {d}%'
},
- data: [
- {value: 0, name: '美团'},
- {value: 24, name: '公众号-企业客户'},
- {value: 0, name: '抖音'},
- {value: 0, name: '渠道'},
- {value: 0, name: '员工'},
- {value: 0, name: '异业'},
- {value: 0, name: '普通客户'}
- ]
+ data: (dashboardData.channelPie && dashboardData.channelPie.length)
+ ? dashboardData.channelPie
+ : []
}]
});
- // 每日销售趋势 - 折线图
+ // 每日销售趋势 - 折线图(使用数据库按天汇总的数据)
var trendChart = echarts.init(document.getElementById('daily-sales-trend-chart'));
trendChart.setOption({
tooltip: {
@@ -605,7 +582,7 @@ layui.config({
xAxis: {
type: 'category',
boundaryGap: false,
- data: []
+ data: dashboardData.trendDates || []
},
yAxis: {
type: 'value',
@@ -635,11 +612,21 @@ layui.config({
itemStyle: {
color: '#4A70F4'
},
- data: []
+ data: dashboardData.trendValues || []
}]
});
+ // 渲染“上月同比”文字
+ var trendCompare = dashboardData.trendCompare || 0;
+ var trendTextDom = $('#trend-compare-text');
+ if (trendCompare > 0) {
+ trendTextDom.css('color', '#52c41a').html('▲ ' + trendCompare.toFixed(2) + '% 上月同比');
+ } else if (trendCompare < 0) {
+ trendTextDom.css('color', '#f56c6c').html('▼ ' + Math.abs(trendCompare).toFixed(2) + '% 上月同比');
+ } else {
+ trendTextDom.css('color', '#999').html('持平 上月同比');
+ }
- // 区域月销售额 - 柱状图
+ // 区域月销售额 - 柱状图(根据地址简单按区域统计)
var regionalChart = echarts.init(document.getElementById('regional-sales-chart'));
regionalChart.setOption({
tooltip: {
@@ -656,7 +643,7 @@ layui.config({
},
xAxis: {
type: 'category',
- data: ['区域1', '区域2', '区域3', '区域4', '区域5', '区域6', '区域7', '区域8']
+ data: dashboardData.regions || []
},
yAxis: {
type: 'value',
@@ -668,7 +655,7 @@ layui.config({
itemStyle: {
color: '#4A70F4'
},
- data: [4668, 3775, 2912, 2200, 1259, 700, 403, 0]
+ data: dashboardData.regionTotals || []
}]
});
diff --git a/application/admin/view/order/eidt.html b/application/admin/view/order/eidt.html
index 46419210..f6fc9512 100644
--- a/application/admin/view/order/eidt.html
+++ b/application/admin/view/order/eidt.html
@@ -298,43 +298,86 @@
setSelectFirst();
function setSelectFirst(default_id) {
+ console.log('setSelectFirst 被调用,default_id:', default_id);
var category_select_html = '';
+ var foundMatch = false;
for (var i in categorys) {
if (categorys[i]['level'] == 1) {
- category_select_html += '';
+ var selected = '';
+ if (default_id && String(categorys[i]['id']) == String(default_id)) {
+ selected = ' selected';
+ foundMatch = true;
+ console.log('找到匹配的省份:', categorys[i]['name'], 'ID:', categorys[i]['id']);
+ }
+ category_select_html += '';
}
}
$('select[name="first_category_id"]').html(category_select_html);
- $('select[name="first_category_id"]').val(default_id);
+ if (default_id) {
+ $('select[name="first_category_id"]').val(String(default_id));
+ console.log('设置省份值:', String(default_id), '是否找到匹配:', foundMatch);
+ }
form.render('select');
}
function setSelectSecond(default_id, parent_id) {
+ console.log('setSelectSecond 被调用,default_id:', default_id, 'parent_id:', parent_id);
parent_id = parent_id === undefined ? $('select[name="first_category_id"]').val() : parent_id;
+ if (!parent_id) {
+ console.log('setSelectSecond: parent_id 为空,返回');
+ return;
+ }
+ parent_id = String(parent_id);
$('select[name="second_category_id"]').html('');
$('select[name="third_category_id"]').html('');
var category_select_html = '';
+ var foundMatch = false;
for (var i in categorys) {
- if (categorys[i]['parent_id'] == parent_id) {
- category_select_html += '';
+ if (String(categorys[i]['parent_id']) == parent_id) {
+ var selected = '';
+ if (default_id && String(categorys[i]['id']) == String(default_id)) {
+ selected = ' selected';
+ foundMatch = true;
+ console.log('找到匹配的城市:', categorys[i]['name'], 'ID:', categorys[i]['id']);
+ }
+ category_select_html += '';
}
}
$('select[name="second_category_id"]').html(category_select_html);
- $('select[name="second_category_id"]').val(default_id);
+ if (default_id) {
+ $('select[name="second_category_id"]').val(String(default_id));
+ console.log('设置城市值:', String(default_id), '是否找到匹配:', foundMatch);
+ }
form.render('select');
}
function setSelectThird(default_id, parent_id) {
+ console.log('setSelectThird 被调用,default_id:', default_id, 'parent_id:', parent_id);
parent_id = parent_id === undefined ? $('select[name="second_category_id"]').val() : parent_id;
+ if (!parent_id) {
+ console.log('setSelectThird: parent_id 为空,返回');
+ return;
+ }
+ parent_id = String(parent_id);
$('select[name="third_category_id"]').html('');
- var first_category_id = $('select[name="first_category_id"]').val();
var category_select_html = '';
+ var foundMatch = false;
+
for (var i in categorys) {
- if (categorys[i]['parent_id'] == parent_id) {
- category_select_html += '';
+ if (String(categorys[i]['parent_id']) == parent_id) {
+ var selected = '';
+ if (default_id && String(categorys[i]['id']) == String(default_id)) {
+ selected = ' selected';
+ foundMatch = true;
+ console.log('找到匹配的区县:', categorys[i]['name'], 'ID:', categorys[i]['id']);
+ }
+ category_select_html += '';
}
}
$('select[name="third_category_id"]').html(category_select_html);
- $('select[name="third_category_id"]').val(default_id);
+ if (default_id) {
+ $('select[name="third_category_id"]').val(String(default_id));
+ console.log('设置区县值:', String(default_id), '是否找到匹配:', foundMatch);
+ }
form.render('select');
}
@@ -465,7 +508,7 @@
}
{notempty name='info'}
var goods_info= {$info|raw|default=''};
- console.log(goods_info);
+ console.log('订单数据:', goods_info);
$('input[name="id"]').val(goods_info['id']);
$('input[name="address"]').val(goods_info['address']);
$('input[name="total_amount"]').val(goods_info['total_amount']);
@@ -474,9 +517,89 @@
$('input[name="phone"]').val(goods_info['mobile']);
$('input[name="store_latitude"]').val(goods_info['lng']);
$('input[name="store_longitude"]').val(goods_info['lat']);
- setSelectFirst(goods_info['province']);
- setSelectSecond(goods_info['city']);
- setSelectThird(goods_info['district']);
+
+ // 设置地区选择器,根据返回的 province、city、district 字段
+ // 注意:需要检查值是否存在,包括0的情况(0是有效的ID值)
+ var province_id = '';
+ var city_id = '';
+ var district_id = '';
+
+ // 检查province字段(包括0值)
+ if (goods_info['province'] !== undefined && goods_info['province'] !== null && goods_info['province'] !== '') {
+ province_id = goods_info['province'];
+ }
+ // 检查city字段(包括0值)
+ if (goods_info['city'] !== undefined && goods_info['city'] !== null && goods_info['city'] !== '') {
+ city_id = goods_info['city'];
+ }
+ // 检查district字段(包括0值)
+ if (goods_info['district'] !== undefined && goods_info['district'] !== null && goods_info['district'] !== '') {
+ district_id = goods_info['district'];
+ }
+
+ console.log('地区数据:', {
+ province: goods_info['province'],
+ city: goods_info['city'],
+ district: goods_info['district'],
+ province_id: province_id,
+ city_id: city_id,
+ district_id: district_id
+ });
+
+ // 初始化地区选择器的函数
+ function initRegionSelectors() {
+ if (province_id !== '') {
+ // 转换为字符串,确保类型匹配
+ province_id = String(province_id);
+
+ // 先设置省份
+ setSelectFirst(province_id);
+
+ // 等待省份选择器渲染完成后再设置城市
+ setTimeout(function() {
+ // 验证省份值是否设置成功
+ var selectedProvince = $('select[name="first_category_id"]').val();
+ console.log('已选省份ID:', selectedProvince, '期望:', province_id);
+
+ if (city_id !== '' && selectedProvince == province_id) {
+ city_id = String(city_id);
+ setSelectSecond(city_id, province_id);
+
+ // 等待城市选择器渲染完成后再设置区县
+ setTimeout(function() {
+ // 验证城市值是否设置成功
+ var selectedCity = $('select[name="second_category_id"]').val();
+ console.log('已选城市ID:', selectedCity, '期望:', city_id);
+
+ if (district_id !== '' && selectedCity == city_id) {
+ district_id = String(district_id);
+ setSelectThird(district_id, city_id);
+
+ setTimeout(function() {
+ var selectedDistrict = $('select[name="third_category_id"]').val();
+ console.log('已选区县ID:', selectedDistrict, '期望:', district_id);
+ // 最后重新渲染一次,确保所有选择器都正确显示
+ form.render('select');
+ }, 100);
+ } else {
+ form.render('select');
+ }
+ }, 300);
+ } else {
+ form.render('select');
+ }
+ }, 300);
+ } else {
+ form.render('select');
+ }
+ }
+
+ // 延迟执行,确保页面完全加载和选择器初始化完成
+ setTimeout(function() {
+ console.log('开始初始化地区选择器...');
+ initRegionSelectors();
+ }, 200);
+
setBrand(goods_info['channel_id']); //部门的修改
setBrandss(goods_info['gord_id']); //部门的修改
diff --git a/application/admin/view/order/lists.html b/application/admin/view/order/lists.html
index 30210722..2c3b47f4 100644
--- a/application/admin/view/order/lists.html
+++ b/application/admin/view/order/lists.html
@@ -73,12 +73,19 @@
height: 62px;
margin-bottom: 5px;
}
- /* 退款状态标红样式 */
- .refund-status-row {
- background-color: #ffebee !important;
+ /* 退款中状态绿色背景 */
+ .refunding-row {
+ background-color: #c8e6c9 !important;
}
- .refund-status-row:hover {
- background-color: #ffcdd2 !important;
+ .refunding-row:hover {
+ background-color: #a5d6a7 !important;
+ }
+ /* 同意退款后淡绿色背景 */
+ .order-status-4-row {
+ background-color: #e8f5e9 !important;
+ }
+ .order-status-4-row:hover {
+ background-color: #c8e6c9 !important;
}
@@ -206,6 +213,7 @@
已支付
已退款
拒退款
+ 已删除
@@ -338,7 +346,11 @@
渠道
备注
分配
+ {{# if(d.del == 0){ }}
删除
+ {{# } else { }}
+
恢复
+ {{# } }}
{{# if(d.order_status == 1){ }}
发货
{{# } }}
@@ -637,19 +649,36 @@
$($(".layui-table-fixed-r .layui-table-body tbody tr")[index]).height($(val).height());
});
- // 如果 refund_status > 0,整行标红显示
+ // 如果 order_status == 4(同意退款),整行淡绿色显示
+ // 如果 refund_status > 0 但 order_status != 4(退款中),整行绿色显示
if (res && res.data && res.data.length > 0) {
res.data.forEach(function(item, index) {
- if (item.refund_status && parseInt(item.refund_status) > 0) {
- // 给主表格行添加红色背景
+ var orderStatus = item.order_status ? parseInt(item.order_status) : 0;
+ var refundStatus = item.refund_status ? parseInt(item.refund_status) : 0;
+
+ // 同意退款后,order_status == 4,显示淡绿色
+ if (orderStatus == 4) {
+ // 给主表格行添加淡绿色背景
var $mainRow = $(".layui-table-main tbody tr").eq(index);
- $mainRow.addClass('refund-status-row');
+ $mainRow.addClass('order-status-4-row');
- // 给固定列的行也添加红色背景
+ // 给固定列的行也添加淡绿色背景
var $fixedLeftRow = $(".layui-table-fixed-l .layui-table-body tbody tr").eq(index);
var $fixedRightRow = $(".layui-table-fixed-r .layui-table-body tbody tr").eq(index);
- $fixedLeftRow.addClass('refund-status-row');
- $fixedRightRow.addClass('refund-status-row');
+ $fixedLeftRow.addClass('order-status-4-row');
+ $fixedRightRow.addClass('order-status-4-row');
+ }
+ // 退款中,refund_status > 0 但 order_status != 4,显示绿色
+ else if (refundStatus > 0) {
+ // 给主表格行添加绿色背景
+ var $mainRow = $(".layui-table-main tbody tr").eq(index);
+ $mainRow.addClass('refunding-row');
+
+ // 给固定列的行也添加绿色背景
+ var $fixedLeftRow = $(".layui-table-fixed-l .layui-table-body tbody tr").eq(index);
+ var $fixedRightRow = $(".layui-table-fixed-r .layui-table-body tbody tr").eq(index);
+ $fixedLeftRow.addClass('refunding-row');
+ $fixedRightRow.addClass('refunding-row');
}
});
}
@@ -835,7 +864,7 @@
});
}
- //取消订单
+ // 退款订单
if(obj.event === 'cancelss'){
layer.confirm('确认订单退款吗?', {
btn: ['确认','取消'] //按钮
@@ -860,7 +889,7 @@
}
- //取消订单
+ // 删除订单(逻辑删除,del 设置为 1)
if(obj.event === 'cancel'){
layer.confirm('确定删除订单的数据?', {
btn: ['确认','取消'] //按钮
@@ -882,6 +911,35 @@
});
}
+ // 恢复订单(del 设置为 0)
+ if(obj.event === 'recover'){
+ layer.confirm('确定恢复该订单吗?', {
+ btn: ['确认','取消'] //按钮
+ }, function(){
+ like.ajax({
+ url: '{:url("order/recover")}?id='+id
+ , type: 'get'
+ , success: function (res) {
+ if (res.code == 1) {
+ layui.layer.msg(res.msg, {
+ offset: '15px'
+ , icon: 1
+ , time: 1000
+ },function () {
+ table.reload('order-lists');
+ });
+ } else {
+ layui.layer.msg(res.msg || '恢复失败', {
+ offset: '15px'
+ , icon: 2
+ , time: 1500
+ });
+ }
+ },
+ });
+ });
+ }
+
//商家备注
if(obj.event === 'remarks') {
like.ajax({
diff --git a/application/admin/view/staff/wages.html b/application/admin/view/staff/wages.html
index 2906e2fa..b15be13f 100644
--- a/application/admin/view/staff/wages.html
+++ b/application/admin/view/staff/wages.html
@@ -90,7 +90,9 @@
-
+
@@ -161,7 +163,7 @@
form.on('submit(export-file)', function(data){
var field = data.field;
$.ajax({
- url: '{:url("order/exportFile")}?type=' + listType,
+ url: '{:url("staff/exportWages")}',
type: 'get',
data: field,
dataType: 'json',
@@ -171,7 +173,7 @@
success: function(res) {
table.exportFile(res.data.exportTitle,res.data.exportData, res.data.exportExt, res.data.exportName);
},
- timeout: 15000
+ timeout: 60000
});
layer.msg('导出中请耐心等待~');
});
diff --git a/application/api/controller/Order.php b/application/api/controller/Order.php
index f2b533b6..b71f0a0e 100644
--- a/application/api/controller/Order.php
+++ b/application/api/controller/Order.php
@@ -91,8 +91,11 @@ class Order extends ApiBase
$order = OrderLogic::add($this->user_id, $info['data'], $post);
+ if ($order['code'] == 0) {
+ $this->_error($order['msg']);
+ }
- return $order;
+ $this->_success('', $order['data']);
}
@@ -572,6 +575,7 @@ class Order extends ApiBase
public function putday()
{
+ $this->_error('该时间内无法自主预约,请联系客服');
$post = $this->request->post();
$hourLists = $post['data']['hourLists'] ?? [];
$orderid = $post['data']['id'] ?? 0;
diff --git a/application/api/controller/Points.php b/application/api/controller/Points.php
index 5b5e34cc..5a4fb012 100644
--- a/application/api/controller/Points.php
+++ b/application/api/controller/Points.php
@@ -22,7 +22,8 @@ class Points extends ApiBase
* @return mixed
*/
public function goodslist(){
- $lists = PointsLogic::goodslist();
+ $clsssId = $this->request->get('classify_id');
+ $lists = PointsLogic::goodslist($clsssId);
$this->_success('获取数据成功',$lists);
}
/**
@@ -38,16 +39,42 @@ class Points extends ApiBase
}
public function goodsSub(){
- $data = $this->request->get();
- $data['user_id']= $this->user_id;
- $user_jf=UserLogic::getUserInfo($this->user_id);
- if($user_jf['user_integral']<$data['price']){
+ $data = $this->request->post();
+
+ // 参数校验
+ if(empty($data) || !is_array($data)){
+ $this->_error('参数错误');
+ }
+ if(empty($data['id']) || empty($data['name']) || !isset($data['price'])){
+ $this->_error('参数不完整');
+ }
+
+ $data['user_id'] = $this->user_id;
+ $user_jf = UserLogic::getUserInfo($this->user_id);
+
+ if($user_jf['user_integral'] < $data['price']){
$this->_error('积分不足');
}else{
- $data = PointsLogic::goodsSub($data);
- $this->_success('兑换成功',$data);
+ $result = PointsLogic::goodsSub($data);
+ if($result['code'] == 1){
+ $this->_success('兑换成功');
+ }else{
+ $this->_error($result['msg']);
+ }
}
-
-
+ }
+
+ //积分订单列表
+ public function orderList()
+ {
+ $data = $this->request->post();
+ // 参数校验
+ if(empty($data) || !is_array($data)){
+ $this->_error('参数错误');
+ }
+ $userId = $this->user_id;
+ $state = isset($data['state']) ? $data['state'] : null;
+ $result = PointsLogic::orderList($userId, $state);
+ $this->_success('获取数据成功',$result);
}
}
\ No newline at end of file
diff --git a/application/api/controller/Share.php b/application/api/controller/Share.php
index 30b1271e..be7808ef 100644
--- a/application/api/controller/Share.php
+++ b/application/api/controller/Share.php
@@ -26,7 +26,7 @@ class Share extends ApiBase
public function shareGoods()
{
$id = $this->request->get('id');
- $url = $this->request->get('url');
+ $url = $this->request->get('page');
$client = $this->client;
if ($id && $url) {
$result = ShareLogic::shareGoods($this->user_id, $id, $url, $client);
diff --git a/application/api/logic/GoodsLogic.php b/application/api/logic/GoodsLogic.php
index 37f3cb7b..c17bfc2b 100644
--- a/application/api/logic/GoodsLogic.php
+++ b/application/api/logic/GoodsLogic.php
@@ -38,7 +38,7 @@ class GoodsLogic{
$goods = new Goods();
//品牌筛选
if(isset($get['brand_id']) && $get['brand_id']) {
- $where[] = ['brand_id', '=', $get['brand_id']];
+ $where[] = ['third_category_id', '=', $get['brand_id']];
}
//分类筛选
if(isset($get['category_id']) && $get['category_id']){
diff --git a/application/api/logic/OrderLogic.php b/application/api/logic/OrderLogic.php
index 1390fae4..1e052998 100644
--- a/application/api/logic/OrderLogic.php
+++ b/application/api/logic/OrderLogic.php
@@ -491,8 +491,8 @@ class OrderLogic extends LogicBase
// 拆分后每个订单的金额需要重新计算,这里先验证原始总金额
// 实际拆分时每个订单会独立计算
} else {
- if($user_money < $data['order_amount']){
- throw new Exception('账户余额不足');
+ if($user_money < $data['order_amount']){
+ throw new Exception('账户余额不足');
}
}
}
@@ -556,10 +556,13 @@ class OrderLogic extends LogicBase
// 创建单个订单
$single_goods_lists = $single_order_data['goods_lists'];
+ if (empty($single_goods_lists)) {
+ throw new Exception('商品信息获取失败');
+ }
$single_goods_id = $single_goods_lists[0]['goods_id'];
-
+
$order = self::addOrder($user_id, $single_order_data, $order_source, $user_address, $single_goods_id);
- $order_id = $order['order_id'];
+ $order_id = $order['order_id'];
$order_ids[] = $order_id;
self::addOrderGoods($order_id, $single_goods_lists);
@@ -590,6 +593,9 @@ class OrderLogic extends LogicBase
}
$single_goods_lists = $single_order_data['goods_lists'];
+ if (empty($single_goods_lists)) {
+ throw new Exception('商品信息获取失败');
+ }
$single_goods_id = $single_goods_lists[0]['goods_id'];
$order = self::addOrder($user_id, $single_order_data, $order_source, $user_address, $single_goods_id);
@@ -607,30 +613,36 @@ class OrderLogic extends LogicBase
}
} else {
// 普通商品:保持原有逻辑
+ if (empty($goods_lists)) {
+ throw new Exception('商品信息获取失败');
+ }
$goods_id = $goods_lists[0]['goods_id'];
$order = self::addOrder($user_id, $data, $order_source, $user_address, $goods_id);
$order_id = $order['order_id'];
$order_ids[] = $order_id;
+
+ self::addOrderGoods($order_id, $goods_lists);
+ self::addOrderAfter($order_id, $user_id, $type, $data);
+
+ //支付方式为余额支付,扣除余额,更新订单状态,支付状态
+ if ($data['pay_way'] == Pay::BALANCE_PAY || $data['order_amount'] == 0) {
+ PayNotifyLogic::handle('order', $order['order_sn'], []);
+ }
- self::addOrderGoods($order_id, $goods_lists);
- self::addOrderAfter($order_id, $user_id, $type, $data);
-
- //支付方式为余额支付,扣除余额,更新订单状态,支付状态
- if ($data['pay_way'] == Pay::BALANCE_PAY || $data['order_amount'] == 0) {
- PayNotifyLogic::handle('order', $order['order_sn'], []);
- }
-
- // 砍价订单处理
- if (isset($post['bargain_launch_id']) and $post['bargain_launch_id'] > 0) {
- $bargainLaunchModel = new BargainLaunch();
- $bargainLaunchModel->where(['id'=>(int)$post['bargain_launch_id']])
- ->update(['order_id'=>$order_id, 'status'=>1]);
+ // 砍价订单处理
+ if (isset($post['bargain_launch_id']) and $post['bargain_launch_id'] > 0) {
+ $bargainLaunchModel = new BargainLaunch();
+ $bargainLaunchModel->where(['id'=>(int)$post['bargain_launch_id']])
+ ->update(['order_id'=>$order_id, 'status'=>1]);
}
}
Db::commit();
- return self::dataSuccess('', ['order_id' => $order_ids[0] ?? 0, 'order_ids' => $order_ids, 'type' => 'order']);
+ if (empty($order_ids)) {
+ throw new Exception('订单创建失败');
+ }
+ return self::dataSuccess('', ['order_id' => $order_ids[0], 'order_ids' => $order_ids, 'type' => 'order']);
} catch (Exception $e) {
Db::rollback();
diff --git a/application/api/logic/PointsLogic.php b/application/api/logic/PointsLogic.php
index 2e3c742e..02a8e328 100644
--- a/application/api/logic/PointsLogic.php
+++ b/application/api/logic/PointsLogic.php
@@ -1,5 +1,6 @@
select();
+ return Db::name('printer_type')->where('del',0)->select();
}
//获取到积分的商品列表
- public static function goodslist(){
- $where=[];
+ public static function goodslist($clsssId){
+ $where=[
+ 'brand_id'=>$clsssId,
+ 'del'=>0
+ ];
$goods = Db::name('printer_goods')
->where($where)
->select();
@@ -34,21 +38,83 @@ class PointsLogic
return $data;
}
+ /**
+ * 积分商品下单(扣减积分并生成订单)
+ * @param array $data ['id','name','price','user_id','number'(可选)]
+ * @return array
+ */
public static function goodsSub($data){
-
- $data=[
- 'name' =>$data['name'],
- 'goods_id' =>$data['id'],
- 'price' =>$data['price'],
- 'number' =>1,
- 'user_id' =>$data['user_id'],
- 'create_time'=>time()
- ];
- $insert=Db::name('printer_order')->data($data)->insert();
- if($insert){
- $user=UserLogic::getUserInfo($data['user_id']);
- db::name('user')->where('id',$data['user_id'])->update(['user_integral'=>$user['user_integral']-$data['price']]);
- // Db::name('printer_goods')->where('')
- }
+ if(empty($data) || !is_array($data)){
+ return ['code'=>0,'msg'=>'参数错误'];
+ }
+ // 基础校验
+ if(empty($data['id']) || empty($data['user_id']) || !isset($data['price'])){
+ return ['code'=>0,'msg'=>'参数不完整'];
+ }
+ $number = isset($data['number']) && intval($data['number'])>0 ? intval($data['number']) : 1;
+ $price = floatval($data['price']);
+ $needIntegral = $price * $number;
+
+ Db::startTrans();
+ try{
+ // 加锁读取用户积分
+ $user = Db::name('user')->where('id',$data['user_id'])->lock(true)->find();
+ if(!$user){
+ throw new Exception('用户不存在');
+ }
+ if($user['user_integral'] < $needIntegral){
+ throw new Exception('积分不足');
+ }
+
+ $orderData = [
+ 'name' => $data['name'] ?? '',
+ 'goods_id' => $data['id'],
+ 'price' => $price,
+ 'number' => $number,
+ 'user_id' => $data['user_id'],
+ 'create_time' => time(),
+ 'address_id' => $data['addressId'],
+ 'state' => 1
+ ];
+
+ $insert = Db::name('printer_order')->insert($orderData);
+ if(!$insert){
+ throw new Exception('下单失败');
+ }
+
+ // 扣减积分
+ Db::name('user')
+ ->where('id',$data['user_id'])
+ ->setDec('user_integral', $needIntegral);
+
+ Db::commit();
+ return ['code'=>1,'msg'=>'兑换成功'];
+ }catch (\Exception $e){
+ Db::rollback();
+ return ['code'=>0,'msg'=>$e->getMessage()];
+ }
+ }
+
+
+ //获取积分订单
+ public static function orderList($userId, $state = null)
+ {
+ $order = new OrderPoints();
+ $query = $order->with([
+ 'address' => function($query){
+ $query->where('del',0)->field('id,address');
+ },
+ 'pointsGoods' => function($query){
+ $query->where('del',0)->field('id,images');
+ }
+ ])->where('user_id', $userId);
+
+ // 如果传了state参数,才添加state条件,否则查询全部
+ if($state !== null && $state !== ''){
+ $query = $query->where('state', $state);
+ }
+
+ $orderArray = $query->paginate(10);
+ return $orderArray;
}
}
\ No newline at end of file
diff --git a/application/api/model/Goods.php b/application/api/model/Goods.php
index ba96d458..3f4143a5 100644
--- a/application/api/model/Goods.php
+++ b/application/api/model/Goods.php
@@ -77,9 +77,22 @@ class Goods extends Model{
$this->setAttr('price',$goods_item[0]['price']);
$this->setAttr('market_price',$goods_item[0]['market_price']);
+ //创建规格值ID到商品项ID的映射
+ $spec_value_to_item = [];
+ foreach ($goods_item as $item) {
+ $spec_value_ids = $item['spec_value_ids'];
+ // spec_value_ids 存储的是规格值ID,可能是一个或多个(逗号分隔)
+ $spec_value_id_array = explode(',', $spec_value_ids);
+ foreach ($spec_value_id_array as $spec_value_id) {
+ $spec_value_to_item[$spec_value_id] = $item['id'];
+ }
+ }
+
//拼接规格
foreach ($spec_value as $item){
if(isset($spec[$item['spec_id']])){
+ //添加对应的商品项ID
+ $item['item_id'] = $spec_value_to_item[$item['id']] ?? 0;
$spec[$item['spec_id']]['spec_value'][]= $item;
}
}
diff --git a/application/api/model/GoodsPoints.php b/application/api/model/GoodsPoints.php
new file mode 100644
index 00000000..59b3a8fa
--- /dev/null
+++ b/application/api/model/GoodsPoints.php
@@ -0,0 +1,10 @@
+hasOne(UserAddress::class, 'id', 'address_id');
+ }
+
+ //关联积分商品
+ public function pointsGoods(): HasOne
+ {
+ return $this->hasOne(GoodsPoints::class, 'id', 'goods_id');
+ }
+}
\ No newline at end of file
diff --git a/application/api/model/UserAddress.php b/application/api/model/UserAddress.php
new file mode 100644
index 00000000..5b452e34
--- /dev/null
+++ b/application/api/model/UserAddress.php
@@ -0,0 +1,10 @@
+where(['id' => $refund_id])->find();
-
+ if ($order['transaction_id'] == ''){
+ throw new Exception('微信订单不存在');
+ }
$data = [
'transaction_id' => $order['transaction_id'],
'refund_sn' => $refund_log['refund_sn'],
diff --git a/application/common/logic/PayNotifyLogic.php b/application/common/logic/PayNotifyLogic.php
index 980e1d95..cbc8dd39 100644
--- a/application/common/logic/PayNotifyLogic.php
+++ b/application/common/logic/PayNotifyLogic.php
@@ -115,27 +115,27 @@ class PayNotifyLogic
//发送通知
- Hook::listen('notice', [
- 'user_id' => $user['id'],
- 'order_id' => $order['id'],
- 'scene' => NoticeSetting::ORDER_PAY_NOTICE,
- ]);
+// Hook::listen('notice', [
+// 'user_id' => $user['id'],
+// 'order_id' => $order['id'],
+// 'scene' => NoticeSetting::ORDER_PAY_NOTICE,
+// ]);
//短信通知
- Hook::listen('sms_send', [
- 'key' => NoticeSetting::ORDER_PAY_NOTICE,
- 'mobile' => $order->mobile,
- 'user_id' => $user->id,
- 'params' => [
- 'nickname' => $user->nickname,
- 'order_sn' => $order->order_sn,
- 'order_amount' => $order->order_amount,
- 'time' => $order->create_time,
- 'total_num' => $order->total_num.'件',
- 'goods_name' => omit_str(($order->order_goods[0]['goods_name'] ?? '商品'), 8)
- ]
- ]);
+// Hook::listen('sms_send', [
+// 'key' => NoticeSetting::ORDER_PAY_NOTICE,
+// 'mobile' => $order->mobile,
+// 'user_id' => $user->id,
+// 'params' => [
+// 'nickname' => $user->nickname,
+// 'order_sn' => $order->order_sn,
+// 'order_amount' => $order->order_amount,
+// 'time' => $order->create_time,
+// 'total_num' => $order->total_num.'件',
+// 'goods_name' => omit_str(($order->order_goods[0]['goods_name'] ?? '商品'), 8)
+// ]
+// ]);
$order_contact_mobile = ConfigServer::get('order_message', 'order_contact_mobile');
//平台短信通知
diff --git a/application/common/model/Ad.php b/application/common/model/Ad.php
index dd38fa1b..bca064e2 100644
--- a/application/common/model/Ad.php
+++ b/application/common/model/Ad.php
@@ -40,7 +40,7 @@ class Ad extends Model{
self::mobile => [
[
'name' => '商品分类',
- 'path' => '/pages/sort/sort',
+ 'path' => '/pages/category/index',
'is_tab' => 1,
],
[
@@ -57,7 +57,7 @@ class Ad extends Model{
self::pc => [
[
'name' => '商品分类',
- 'path' => '/category',
+ 'path' => '/category/index',
'is_tab' => 0,
],
[
@@ -67,7 +67,7 @@ class Ad extends Model{
],
[
'name' => '个人中心',
- 'path' => '/user/profile',
+ 'path' => '/user/user',
'is_tab' => 0,
],
],
diff --git a/application/common/server/storage/engine/Aliyun.php b/application/common/server/storage/engine/Aliyun.php
index 02745b79..c49ce82e 100644
--- a/application/common/server/storage/engine/Aliyun.php
+++ b/application/common/server/storage/engine/Aliyun.php
@@ -24,7 +24,7 @@ class Aliyun extends Server
parent::__construct();
$this->config = $config;
}
-
+
/**
* 创建并配置 OssClient
* @return OssClient