Просмотр исходного кода

【程序目录】更新开源5.4版本

吴昊天 1 год назад
Родитель
Сommit
9e1a8c3671
100 измененных файлов с 3817 добавлено и 1100 удалено
  1. 3 3
      crmeb/.version
  2. 22 51
      crmeb/app/Request.php
  3. 3 28
      crmeb/app/adminapi/controller/Common.php
  4. 1404 161
      crmeb/app/adminapi/controller/UpgradeController.php
  5. 2 1
      crmeb/app/adminapi/controller/v1/agent/Division.php
  6. 8 0
      crmeb/app/adminapi/controller/v1/cms/Article.php
  7. 4 0
      crmeb/app/adminapi/controller/v1/cms/ArticleCategory.php
  8. 1 0
      crmeb/app/adminapi/controller/v1/marketing/StoreBargain.php
  9. 1 0
      crmeb/app/adminapi/controller/v1/marketing/StoreCombination.php
  10. 309 140
      crmeb/app/adminapi/controller/v1/order/StoreOrderInvoice.php
  11. 2 2
      crmeb/app/adminapi/controller/v1/product/StoreProduct.php
  12. 17 1
      crmeb/app/adminapi/controller/v1/product/StoreProductReply.php
  13. 16 1
      crmeb/app/adminapi/controller/v1/setting/SystemConfig.php
  14. 169 7
      crmeb/app/adminapi/controller/v1/setting/SystemCrud.php
  15. 0 74
      crmeb/app/adminapi/controller/v1/statistic/FlowStatistic.php
  16. 28 3
      crmeb/app/adminapi/controller/v1/system/AppVersion.php
  17. 54 1
      crmeb/app/adminapi/controller/v1/system/SystemCrontab.php
  18. 9 3
      crmeb/app/adminapi/controller/v1/system/SystemDatabackup.php
  19. 157 0
      crmeb/app/adminapi/controller/v1/system/SystemEvent.php
  20. 16 0
      crmeb/app/adminapi/route/order.php
  21. 2 0
      crmeb/app/adminapi/route/product.php
  22. 37 1
      crmeb/app/adminapi/route/system.php
  23. 1 1
      crmeb/app/api/controller/pc/ProductController.php
  24. 72 0
      crmeb/app/api/controller/pc/PublicController.php
  25. 1 1
      crmeb/app/api/controller/v1/CrontabController.php
  26. 21 0
      crmeb/app/api/controller/v1/LoginController.php
  27. 30 0
      crmeb/app/api/controller/v1/PublicController.php
  28. 1 1
      crmeb/app/api/controller/v1/activity/StoreBargainController.php
  29. 1 1
      crmeb/app/api/controller/v1/order/OtherOrderController.php
  30. 35 5
      crmeb/app/api/controller/v1/order/StoreOrderController.php
  31. 12 0
      crmeb/app/api/controller/v1/order/StoreOrderRefundController.php
  32. 36 4
      crmeb/app/api/controller/v1/publics/ArticleController.php
  33. 9 4
      crmeb/app/api/controller/v1/store/StoreProductController.php
  34. 8 1
      crmeb/app/api/controller/v1/user/DivisionController.php
  35. 4 1
      crmeb/app/api/controller/v1/user/UserAddressController.php
  36. 3 0
      crmeb/app/api/controller/v1/user/UserSignController.php
  37. 16 0
      crmeb/app/api/controller/v2/order/StoreOrderInvoiceController.php
  38. 3 0
      crmeb/app/api/route/pc.php
  39. 4 3
      crmeb/app/api/route/v1.php
  40. 2 0
      crmeb/app/api/route/v2.php
  41. 45 2
      crmeb/app/common.php
  42. 1 1
      crmeb/app/dao/activity/bargain/StoreBargainDao.php
  43. 1 1
      crmeb/app/dao/activity/combination/StoreCombinationDao.php
  44. 2 1
      crmeb/app/dao/activity/combination/StorePinkDao.php
  45. 1 1
      crmeb/app/dao/activity/seckill/StoreSeckillDao.php
  46. 16 24
      crmeb/app/dao/article/ArticleDao.php
  47. 1 1
      crmeb/app/dao/order/OtherOrderDao.php
  48. 2 2
      crmeb/app/dao/order/StoreOrderDao.php
  49. 2 2
      crmeb/app/dao/product/product/StoreProductReplyDao.php
  50. 2 1
      crmeb/app/dao/product/product/StoreProductReplyStoreProductDao.php
  51. 25 0
      crmeb/app/dao/system/SystemCrudListDao.php
  52. 18 0
      crmeb/app/dao/system/SystemEventDao.php
  53. 18 0
      crmeb/app/dao/system/SystemEventDataDao.php
  54. 2 2
      crmeb/app/event.php
  55. 56 0
      crmeb/app/jobs/OrderInvoiceJob.php
  56. 26 0
      crmeb/app/listener/CustomEventListener.php
  57. 0 79
      crmeb/app/listener/crontab/SystemCrontabListener.php
  58. 9 1
      crmeb/app/listener/order/OrderPaySuccessListener.php
  59. 1 1
      crmeb/app/model/activity/combination/StoreCombination.php
  60. 10 4
      crmeb/app/model/article/Article.php
  61. 19 11
      crmeb/app/model/order/OtherOrder.php
  62. 148 141
      crmeb/app/model/order/StoreOrderInvoice.php
  63. 1 1
      crmeb/app/model/product/product/StoreProduct.php
  64. 10 0
      crmeb/app/model/product/product/StoreProductReply.php
  65. 18 4
      crmeb/app/model/system/SystemCrudData.php
  66. 30 0
      crmeb/app/model/system/SystemCrudList.php
  67. 23 0
      crmeb/app/model/system/SystemEvent.php
  68. 23 0
      crmeb/app/model/system/SystemEventData.php
  69. 15 1
      crmeb/app/model/system/config/SystemConfig.php
  70. 20 0
      crmeb/app/model/system/crontab/SystemCrontab.php
  71. 36 0
      crmeb/app/outapi/controller/User.php
  72. 2 0
      crmeb/app/outapi/route/route.php
  73. 12 1
      crmeb/app/services/BaseServices.php
  74. 5 4
      crmeb/app/services/activity/bargain/StoreBargainServices.php
  75. 1 1
      crmeb/app/services/activity/bargain/StoreBargainUserServices.php
  76. 6 4
      crmeb/app/services/activity/combination/StoreCombinationServices.php
  77. 2 2
      crmeb/app/services/activity/integral/StoreIntegralServices.php
  78. 2 2
      crmeb/app/services/activity/integral/StorePointRecordServices.php
  79. 1 1
      crmeb/app/services/activity/lottery/LuckLotteryRecordServices.php
  80. 10 0
      crmeb/app/services/activity/lottery/LuckLotteryServices.php
  81. 8 11
      crmeb/app/services/activity/seckill/StoreSeckillServices.php
  82. 16 12
      crmeb/app/services/agent/AgentLevelServices.php
  83. 23 17
      crmeb/app/services/agent/DivisionServices.php
  84. 28 9
      crmeb/app/services/article/ArticleServices.php
  85. 13 19
      crmeb/app/services/message/SystemNotificationServices.php
  86. 1 1
      crmeb/app/services/message/notice/EnterpriseWechatService.php
  87. 1 1
      crmeb/app/services/order/OtherOrderServices.php
  88. 18 6
      crmeb/app/services/order/StoreCartServices.php
  89. 1 0
      crmeb/app/services/order/StoreOrderCartInfoServices.php
  90. 18 0
      crmeb/app/services/order/StoreOrderCreateServices.php
  91. 14 1
      crmeb/app/services/order/StoreOrderDeliveryServices.php
  92. 394 217
      crmeb/app/services/order/StoreOrderInvoiceServices.php
  93. 39 2
      crmeb/app/services/order/StoreOrderRefundServices.php
  94. 27 1
      crmeb/app/services/order/StoreOrderServices.php
  95. 17 4
      crmeb/app/services/order/StoreOrderSuccessServices.php
  96. 44 2
      crmeb/app/services/order/StoreOrderTakeServices.php
  97. 1 2
      crmeb/app/services/order/StoreOrderWriteOffServices.php
  98. 8 0
      crmeb/app/services/product/product/StoreProductRelationServices.php
  99. 1 0
      crmeb/app/services/product/product/StoreProductReplyServices.php
  100. 0 0
      crmeb/app/services/product/product/StoreProductServices.php

+ 3 - 3
crmeb/.version

@@ -1,5 +1,5 @@
-version=CRMEB-KY v5.3.0
-version_code=530
-platform=GITEE
+version=CRMEB-KY v5.4.0
+version_code=540
+platform=gitee
 app_id=ze7x9rxsv09l6pvsyo
 app_key=fuF7U9zaybLa5gageVQzxtxQMFnvU2OI

+ 22 - 51
crmeb/app/Request.php

@@ -34,7 +34,7 @@ class Request extends \think\Request
      * @var array
      */
     protected $except = ['menu_path', 'api_url', 'unique_auth',
-        'description', 'custom_form', 'content', 'tableField', 'url'];
+                         'description', 'custom_form', 'content', 'tableField', 'url', 'customCode'];
 
     /**
      * 获取请求的数据
@@ -49,7 +49,7 @@ class Request extends \think\Request
         $i = 0;
         foreach ($params as $param) {
             if (!is_array($param)) {
-                $p[$suffix == true ? $i++ : $param] = $this->filterWord(is_string($this->param($param)) ? trim($this->param($param)) : $this->param($param), $filter && !in_array($param, $this->except));
+                $p[$suffix == true ? $i++ : $param] = $this->param($param);
             } else {
                 if (!isset($param[1])) $param[1] = null;
                 if (!isset($param[2])) $param[2] = '';
@@ -61,70 +61,41 @@ class Request extends \think\Request
                     $keyName = $param[0];
                 }
 
-                $p[$suffix == true ? $i++ : ($param[3] ?? $keyName)] = $this->filterWord(
-                    is_string($this->param($name, $param[1], $param[2])) ?
-                        trim($this->param($name, $param[1], $param[2])) :
-                        $this->param($name, $param[1], $param[2]),
-                    $filter && !in_array($keyName, $this->except));
+                $p[$suffix == true ? $i++ : ($param[3] ?? $keyName)] = $this->param($name, $param[1], $param[2]);
             }
         }
+
+        if ($filter && $p) {
+            $p = $this->filterArrayValues($p);
+        }
+
         return $p;
     }
 
     /**
-     * 过滤接受的参数
+     * 过滤接数组中的字符串
      * @param $str
      * @param bool $filter
      * @return array|mixed|string|string[]
      */
-    public function filterWord($str, bool $filter = true)
+    public function filterArrayValues($array)
     {
-        if (!$str || !$filter) return $str;
-        // 把数据过滤
-        $farr = [
-            "/<(\\/?)(script|i?frame|style|html|body|title|link|meta|object|\\?|\\%)([^>]*?)>/isU",
-            "/(<[^>]*)on[a-zA-Z]+\s*=([^>]*>)/isU",
-            '/phar/is',
-            "/select|join|where|drop|like|modify|rename|insert|update|table|database|alter|truncate|\'|\/\*|\.\.\/|\.\/|union|into|load_file|outfile/is"
-        ];
-        if (is_array($str)) {
-            foreach ($str as &$v) {
-                if (is_array($v)) {
-                    foreach ($v as &$vv) {
-                        if (!is_array($vv)) {
-                            $vv = $this->replaceWord($farr, $vv);
-                        }
-                    }
+        $result = [];
+        foreach ($array as $key => $value) {
+            if (is_array($value)) {
+                // 如果值是数组,递归调用 filterArrayValues
+                $result[$key] = $this->filterArrayValues($value);
+            } else {
+                if (in_array($key, $this->except) || is_int($value) || is_null($value)) {
+                    $result[$key] = $value;
                 } else {
-                    $v = $this->replaceWord($farr, $v);
+                    // 如果值是字符串,过滤特殊字符
+                    $result[$key] = filter_str($value);
                 }
-            }
-        } else {
-            $str = $this->replaceWord($farr, $str);
-        }
-        return $str;
-    }
 
-    /**
-     * 替换
-     * @param $farr
-     * @param $str
-     * @return array|string|string[]|null
-     * @author: 吴汐
-     * @email: 442384644@qq.com
-     * @date: 2023/9/19
-     */
-    public function replaceWord($farr, $str)
-    {
-        if (filter_var($str, FILTER_VALIDATE_URL)) {
-            $url = parse_url($str);
-            if (!isset($url['scheme'])) return $str;
-            $host = $url['scheme'] . '://' . $url['host'];
-            $str = $host . preg_replace($farr, '', str_replace($host, '', $str));
-        } else {
-            $str = preg_replace($farr, '', $str);
+            }
         }
-        return $str;
+        return $result;
     }
 
     /**

+ 3 - 28
crmeb/app/adminapi/controller/Common.php

@@ -60,34 +60,6 @@ class Common extends AuthController
             'version' => $version
         ]);
         $res = $res ? json_decode($res, true) : [];
-
-        //兼容test.
-        if (!isset($res['data']['status']) || $res['data']['status'] !== 1) {
-            $host = str_replace('test.', '', $host);
-            $res = HttpService::request('http://authorize.crmeb.net/api/auth_cert_query', 'post', [
-                'domain_name' => $host,
-                'label' => 34,
-                'version' => $version
-            ]);
-            $res = $res ? json_decode($res, true) : [];
-        }
-
-        //如果是主域名兼容www.
-        if (!isset($res['data']['status']) || $res['data']['status'] !== 1) {
-            $host = str_replace('www.', '', $host);
-            $res = HttpService::request('http://authorize.crmeb.net/api/auth_cert_query', 'post', [
-                'domain_name' => $host,
-                'label' => 34,
-                'version' => $version
-            ]);
-            $res = $res ? json_decode($res, true) : [];
-        }
-
-        //升级状态
-//        /** @var UpgradeServices $upgradeServices */
-//        $upgradeServices = app()->make(UpgradeServices::class);
-//        $upgradeStatus = $upgradeServices->getUpgradeStatus();
-
         $status = $res['data']['status'] ?? -9;
         switch ((int)$status) {
             case 1:
@@ -447,6 +419,9 @@ class Common extends AuthController
         $configMenusList = $menusServices->getColumn([['id', 'in', $configTabIds]], 'menu_name as title,menu_path as path,id', 'id');
         // 将配置项列表中的菜单ID与配置项标签对应的菜单ID对应起来
         foreach ($configAllList as $item2) {
+            if ($item2['menus_id'] == 0) {
+                continue;
+            }
             $menusList[] = [
                 'title' => $configMenusList[$item2['menus_id']]['title'] . '-' . $item2['title'],
                 'path' => $configMenusList[$item2['menus_id']]['path'] . '?tab_id=' . $item2['config_tab_id'],

Разница между файлами не показана из-за своего большого размера
+ 1404 - 161
crmeb/app/adminapi/controller/UpgradeController.php


+ 2 - 1
crmeb/app/adminapi/controller/v1/agent/Division.php

@@ -99,7 +99,7 @@ class Division extends AuthController
             ['account', ''],
             ['pwd', ''],
             ['conf_pwd', ''],
-            ['real_name', ''],
+            ['division_name', ''],
             ['roles', []],
             ['image', []]
         ]);
@@ -134,6 +134,7 @@ class Division extends AuthController
             ['division_percent', 0],
             ['division_end_time', ''],
             ['division_status', 1],
+            ['division_name', ''],
             ['edit', 0],
             ['image', []],
         ]);

+ 8 - 0
crmeb/app/adminapi/controller/v1/cms/Article.php

@@ -40,6 +40,10 @@ class Article extends AuthController
     /**
      * 获取列表
      * @return mixed
+     * @throws \ReflectionException
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
      */
     public function index()
     {
@@ -81,6 +85,10 @@ class Article extends AuthController
      * 获取单个文章数据
      * @param int $id
      * @return mixed
+     * @throws \ReflectionException
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
      */
     public function read($id = 0)
     {

+ 4 - 0
crmeb/app/adminapi/controller/v1/cms/ArticleCategory.php

@@ -87,6 +87,7 @@ class ArticleCategory extends AuthController
         $data['add_time'] = time();
         $this->service->save($data);
         CacheService::delete('ARTICLE_CATEGORY');
+        CacheService::delete('ARTICLE_CATEGORY_PC');
         return app('json')->success(100021);
     }
 
@@ -121,6 +122,7 @@ class ArticleCategory extends AuthController
         ]);
         $this->service->update($data);
         CacheService::delete('ARTICLE_CATEGORY');
+        CacheService::delete('ARTICLE_CATEGORY_PC');
         return app('json')->success(100001);
     }
 
@@ -135,6 +137,7 @@ class ArticleCategory extends AuthController
         if (!$id) return app('json')->fail(100100);
         $this->service->del($id);
         CacheService::delete('ARTICLE_CATEGORY');
+        CacheService::delete('ARTICLE_CATEGORY_PC');
         return app('json')->success(100002);
     }
 
@@ -150,6 +153,7 @@ class ArticleCategory extends AuthController
         if ($status == '' || $id == 0) return app('json')->fail(100100);
         $this->service->setStatus($id, $status);
         CacheService::delete('ARTICLE_CATEGORY');
+        CacheService::delete('ARTICLE_CATEGORY_PC');
         return app('json')->success(100014);
     }
 

+ 1 - 0
crmeb/app/adminapi/controller/v1/marketing/StoreBargain.php

@@ -65,6 +65,7 @@ class StoreBargain extends AuthController
             ['info', ''],
             ['unit_name', ''],
             ['section_time', []],
+            ['image', ''],
             ['images', []],
             ['bargain_max_price', 0],
             ['bargain_min_price', 0],

+ 1 - 0
crmeb/app/adminapi/controller/v1/marketing/StoreCombination.php

@@ -86,6 +86,7 @@ class StoreCombination extends AuthController
             [['title', 's'], ''],
             [['info', 's'], ''],
             [['unit_name', 's'], ''],
+            ['image', ''],
             ['images', []],
             ['section_time', []],
             [['is_host', 'd'], 0],

+ 309 - 140
crmeb/app/adminapi/controller/v1/order/StoreOrderInvoice.php

@@ -1,140 +1,309 @@
-<?php
-// +----------------------------------------------------------------------
-// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
-// +----------------------------------------------------------------------
-// | Copyright (c) 2016~2023 https://www.crmeb.com All rights reserved.
-// +----------------------------------------------------------------------
-// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
-// +----------------------------------------------------------------------
-// | Author: CRMEB Team <admin@crmeb.com>
-// +----------------------------------------------------------------------
-namespace app\adminapi\controller\v1\order;
-
-use app\adminapi\controller\AuthController;
-use app\services\order\StoreOrderInvoiceServices;
-use app\services\order\StoreOrderServices;
-use app\services\product\product\StoreProductServices;
-use app\services\system\store\SystemStoreServices;
-use app\services\user\UserServices;
-use think\facade\App;
-
-/**
- * 发票管理
- * Class StoreOrderInvoice
- * @package app\adminapi\controller\v1\order
- */
-class StoreOrderInvoice extends AuthController
-{
-
-    /**
-     * StoreOrderInvoice constructor.
-     * @param App $app
-     * @param StoreOrderInvoiceServices $services
-     */
-    public function __construct(App $app, StoreOrderInvoiceServices $services)
-    {
-        parent::__construct($app);
-        $this->services = $services;
-    }
-
-    /**
-     * 获取订单类型数量
-     * @return mixed
-     */
-    public function chart()
-    {
-        $where = $this->request->getMore([
-            ['data', '', '', 'time'],
-            ['real_name', ''],
-            ['field_key', ''],
-            [['type', 'd'], 0],
-        ]);
-        $data = $this->services->chart($where);
-        return app('json')->success($data);
-    }
-
-    /**
-     * 查询发票列表
-     * @return mixed
-     */
-    public function list()
-    {
-        $where = $this->request->getMore([
-            ['status', 0],
-            ['real_name', ''],
-            ['header_type', ''],
-            ['type', ''],
-            ['data', '', '', 'time'],
-            ['field_key', ''],
-        ]);
-        return app('json')->success($this->services->getList($where));
-    }
-
-
-    /**
-     * 设置发票状态
-     * @param string $id
-     * @return mixed
-     */
-    public function set_invoice($id = '')
-    {
-        if ($id == '') return app('json')->fail(100100);
-        $data = $this->request->postMore([
-            ['is_invoice', 0],
-            ['invoice_number', 0],
-            ['remark', '']
-        ]);
-        if ($data['is_invoice'] == 1 && !$data['invoice_number']) {
-            return app('json')->fail(400166);
-        }
-        if ($data['invoice_number'] && !preg_match('/^\d{8,10}$/', $data['invoice_number'])) {
-            return app('json')->fail(400167);
-        }
-        $this->services->setInvoice((int)$id, $data);
-        return app('json')->success(100014);
-    }
-
-    /**
-     * 订单详情
-     * @param $id 订单id
-     * @return mixed
-     */
-    public function orderInfo(StoreProductServices $productServices, StoreOrderServices $orderServices, $id)
-    {
-        if (!$id || !($orderInfo = $orderServices->get($id))) {
-            return app('json')->fail(400118);
-        }
-        /** @var UserServices $services */
-        $services = app()->make(UserServices::class);
-        $userInfo = $services->get($orderInfo['uid']);
-        if (!$userInfo) {
-            return app('json')->fail(400119);
-        }
-        $userInfo = $userInfo->hidden(['pwd', 'add_ip', 'last_ip', 'login_type']);
-        $userInfo['spread_name'] = '';
-        if ($userInfo['spread_uid'])
-            $userInfo['spread_name'] = $services->value(['uid' => $userInfo['spread_uid']], 'nickname');
-        $orderInfo = $orderServices->tidyOrder($orderInfo->toArray(), true, true);
-        //核算优惠金额
-        $vipTruePrice = array_column($orderInfo['cartInfo'], 'vip_sum_truePrice');
-        $vipTruePrice = array_sum($vipTruePrice);
-        $orderInfo['vip_true_price'] = $vipTruePrice ?: 0;
-
-        $orderInfo['add_time'] = $orderInfo['_add_time'] ?? '';
-        $productId = array_column($orderInfo['cartInfo'], 'product_id');
-        $cateData = $productServices->productIdByProductCateName($productId);
-        foreach ($orderInfo['cartInfo'] as &$item) {
-            $item['class_name'] = $cateData[$item['product_id']] ?? '';
-        }
-        if ($orderInfo['store_id'] && $orderInfo['shipping_type'] == 2) {
-            /** @var  $storeServices */
-            $storeServices = app()->make(SystemStoreServices::class);
-            $orderInfo['_store_name'] = $storeServices->value(['id' => $orderInfo['store_id']], 'name');
-        } else {
-            $orderInfo['_store_name'] = '';
-        }
-        $userInfo = $userInfo->toArray();
-        $invoice = $this->services->getOne(['order_id' => $id]);
-        return app('json')->success(compact('orderInfo', 'userInfo', 'invoice'));
-    }
-}
+<?php
+// +----------------------------------------------------------------------
+// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2016~2023 https://www.crmeb.com All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
+// +----------------------------------------------------------------------
+// | Author: CRMEB Team <admin@crmeb.com>
+// +----------------------------------------------------------------------
+namespace app\adminapi\controller\v1\order;
+
+use app\adminapi\controller\AuthController;
+use app\services\order\StoreOrderCartInfoServices;
+use app\services\order\StoreOrderInvoiceServices;
+use app\services\order\StoreOrderServices;
+use app\services\product\product\StoreProductServices;
+use app\services\serve\ServeServices;
+use app\services\system\store\SystemStoreServices;
+use app\services\user\UserServices;
+use think\facade\App;
+
+/**
+ * 发票管理
+ * Class StoreOrderInvoice
+ * @package app\adminapi\controller\v1\order
+ */
+class StoreOrderInvoice extends AuthController
+{
+
+    /**
+     * StoreOrderInvoice constructor.
+     * @param App $app
+     * @param StoreOrderInvoiceServices $services
+     */
+    public function __construct(App $app, StoreOrderInvoiceServices $services)
+    {
+        parent::__construct($app);
+        $this->services = $services;
+    }
+
+    /**
+     * 获取订单类型数量
+     * @return mixed
+     */
+    public function chart()
+    {
+        $where = $this->request->getMore([
+            ['data', '', '', 'time'],
+            ['real_name', ''],
+            ['field_key', ''],
+            [['type', 'd'], 0],
+        ]);
+        $data = $this->services->chart($where);
+        return app('json')->success($data);
+    }
+
+    /**
+     * 查询发票列表
+     * @return mixed
+     */
+    public function list()
+    {
+        $where = $this->request->getMore([
+            ['status', 0],
+            ['real_name', ''],
+            ['header_type', ''],
+            ['type', ''],
+            ['data', '', '', 'time'],
+            ['field_key', ''],
+        ]);
+        return app('json')->success($this->services->getList($where));
+    }
+
+
+    /**
+     * 设置发票状态
+     * @param string $id
+     * @return mixed
+     */
+    public function set_invoice($id = '')
+    {
+        if ($id == '') return app('json')->fail(100100);
+        $data = $this->request->postMore([
+            ['is_invoice', 0],
+            ['invoice_number', 0],
+            ['remark', '']
+        ]);
+        if ($data['is_invoice'] == 1 && !$data['invoice_number']) {
+            return app('json')->fail(400166);
+        }
+        if ($data['invoice_number'] && !preg_match('/^\d{8,10}$/', $data['invoice_number'])) {
+            return app('json')->fail(400167);
+        }
+        $this->services->setInvoice((int)$id, $data);
+        return app('json')->success(100014);
+    }
+
+    /**
+     * 订单详情
+     * @param $id 订单id
+     * @return mixed
+     */
+    public function orderInfo(StoreProductServices $productServices, StoreOrderServices $orderServices, $id)
+    {
+        if (!$id || !($orderInfo = $orderServices->get($id))) {
+            return app('json')->fail(400118);
+        }
+        /** @var UserServices $services */
+        $services = app()->make(UserServices::class);
+        $userInfo = $services->get($orderInfo['uid']);
+        if (!$userInfo) {
+            return app('json')->fail(400119);
+        }
+        $userInfo = $userInfo->hidden(['pwd', 'add_ip', 'last_ip', 'login_type']);
+        $userInfo['spread_name'] = '';
+        if ($userInfo['spread_uid'])
+            $userInfo['spread_name'] = $services->value(['uid' => $userInfo['spread_uid']], 'nickname');
+        $orderInfo = $orderServices->tidyOrder($orderInfo->toArray(), true, true);
+        //核算优惠金额
+        $vipTruePrice = array_column($orderInfo['cartInfo'], 'vip_sum_truePrice');
+        $vipTruePrice = array_sum($vipTruePrice);
+        $orderInfo['vip_true_price'] = $vipTruePrice ?: 0;
+
+        $orderInfo['add_time'] = $orderInfo['_add_time'] ?? '';
+        $productId = array_column($orderInfo['cartInfo'], 'product_id');
+        $cateData = $productServices->productIdByProductCateName($productId);
+        foreach ($orderInfo['cartInfo'] as &$item) {
+            $item['class_name'] = $cateData[$item['product_id']] ?? '';
+        }
+        if ($orderInfo['store_id'] && $orderInfo['shipping_type'] == 2) {
+            /** @var  $storeServices */
+            $storeServices = app()->make(SystemStoreServices::class);
+            $orderInfo['_store_name'] = $storeServices->value(['id' => $orderInfo['store_id']], 'name');
+        } else {
+            $orderInfo['_store_name'] = '';
+        }
+        $userInfo = $userInfo->toArray();
+        $invoice = $this->services->getOne(['order_id' => $id]);
+        return app('json')->success(compact('orderInfo', 'userInfo', 'invoice'));
+    }
+
+    /**
+     * 获取电子发票配置信息
+     * @return \think\Response
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/5/16
+     */
+    public function elecInvoiceConfig()
+    {
+        $data = [
+            'elec_invoice' => (int)sys_config('elec_invoice'),
+            'auto_invoice' => (int)sys_config('auto_invoice'),
+            'elec_invoice_cate' => (int)sys_config('elec_invoice_cate'),
+            'elec_invoice_cate_name' => sys_config('elec_invoice_cate_name'),
+            'elec_invoice_tax_rate' => (int)sys_config('elec_invoice_tax_rate')
+        ];
+        return app('json')->success($data);
+    }
+
+    /**
+     * 获取发票开具页面iframe地址
+     * @param $id
+     * @return \think\Response
+     * @throws \ReflectionException
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/5/13
+     */
+    public function invoiceIssuanceUrl($id)
+    {
+        if (sys_config('elec_invoice', 1) != 1) {
+            return app('json')->fail('电子发票功能未开启,请在一号通中开启并且在商城后台一号通配置中开启');
+        }
+        $info = $this->services->getOne(['id' => $id]);
+        $unique = app()->make(StoreOrderServices::class)->value(['id' => $info['order_id']], 'order_id');
+        $cartInfo = app()->make(StoreOrderCartInfoServices::class)->getOrderCartInfo($info['order_id']);
+        $goods = [];
+        foreach ($cartInfo as $item) {
+            $goods[] = [
+                'store_name' => $item['cart_info']['productInfo']['store_name'],
+                'unit_price' => bcadd($item['cart_info']['sum_price'], $item['cart_info']['postage_price'], 2),
+                'num' => $item['cart_info']['cart_num']
+            ];
+        }
+        $data = [];
+        $data['unique'] = $unique;
+        $data['goods'] = $goods;
+        $data['account_name'] = $info['name'];
+        $data['email'] = $info['email'];
+        if ($info['header_type'] == 1) {
+            $data['invoice_type'] = 82;
+            $data['is_enterprise'] = 0;
+        } else {
+            $data['invoice_type'] = 81;
+            $data['tax_id'] = $info['duty_number'];
+            $data['is_enterprise'] = 1;
+        }
+        $invoice = app()->make(ServeServices::class)->invoice();
+        return app('json')->success($invoice->invoiceIssuanceUrl($data));
+    }
+
+    /**
+     * 保存发票信息
+     * @param $id
+     * @return \think\Response
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/5/14
+     */
+    public function saveInvoiceInfo($id)
+    {
+        $data = $this->request->postMore([
+            ['invoice_num', ''],
+            ['invoice_type', ''],
+            ['invoice_serial_number', ''],
+        ]);
+        $info = $this->services->getOne(['id' => $id]);
+        $data['unique_num'] = app()->make(StoreOrderServices::class)->value(['id' => $info['order_id']], 'order_id');
+        $data['is_invoice'] = 1;
+        $data['invoice_time'] = time();
+        $this->services->update($id, $data);
+        return app('json')->success('保存成功');
+    }
+
+    /**
+     * 查看发票详情
+     * @param $id
+     * @return \think\Response
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/5/14
+     */
+    public function invoiceInfo($id)
+    {
+        $info = $this->services->getOne(['id' => $id]);
+        $invoice = app()->make(ServeServices::class)->invoice();
+        return app('json')->success($invoice->invoiceInfo($info['invoice_num']));
+    }
+
+    /**
+     * 下载发票
+     * @param $id
+     * @return \think\Response
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/5/14
+     */
+    public function downInvoice($id)
+    {
+        $info = $this->services->getOne(['id' => $id]);
+        $invoice = app()->make(ServeServices::class)->invoice();
+        return app('json')->success($invoice->downloadInvoice($info['invoice_num']));
+    }
+
+    /**
+     * 电子发票分类
+     * @return \think\Response
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/5/15
+     */
+    public function invoiceCategory()
+    {
+        $where = $this->request->getMore([
+            ['name', ''],
+            ['page', 1],
+            ['limit', 100],
+        ]);
+        $invoice = app()->make(ServeServices::class)->invoice();
+        return app('json')->success($invoice->category($where));
+    }
+
+    /**
+     * 开具发票
+     * @param $id
+     * @return \think\Response
+     * @throws \ReflectionException
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/5/15
+     */
+    public function invoiceIssuance($id)
+    {
+        $this->services->invoiceIssuance($id);
+        return app('json')->success('开票成功');
+    }
+
+    /**
+     * 负数发票开具
+     * @param $id
+     * @return \think\Response
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/5/16
+     */
+    public function redInvoiceIssuance($id)
+    {
+        $this->services->redInvoiceIssuance($id);
+        return app('json')->success('开具负数发票成功');
+    }
+}

+ 2 - 2
crmeb/app/adminapi/controller/v1/product/StoreProduct.php

@@ -299,9 +299,9 @@ class StoreProduct extends AuthController
             ['is_live', 0],
             ['is_new', ''],
             ['is_virtual', -1],
-            ['is_presale', -1]
+            ['is_presale', -1],
+            ['is_show', 1],
         ]);
-        $where['is_show'] = 1;
         $where['is_del'] = 0;
         $where['cate_id'] = stringToIntArray($where['cate_id']);
         /** @var StoreCategoryServices $storeCategoryServices */

+ 17 - 1
crmeb/app/adminapi/controller/v1/product/StoreProductReply.php

@@ -41,7 +41,8 @@ class StoreProductReply extends AuthController
             ['data', ''],
             ['product_id', 0],
             ['key', ''],
-            ['order', '']
+            ['order', ''],
+            ['status', ''],
         ]);
         $list = $this->services->sysPage($where);
         return app('json')->success($list);
@@ -110,4 +111,19 @@ class StoreProductReply extends AuthController
         $this->services->saveReply($data);
         return app('json')->success(100000);
     }
+
+    /**
+     * 商品评论审核
+     * @param $id
+     * @param $status
+     * @return \think\Response
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/4/22
+     */
+    public function set_status($id, $status)
+    {
+        $this->services->update($id, ['status' => $status]);
+        return app('json')->success($status == 1 ? '审核通过' : '拒绝成功');
+    }
 }

+ 16 - 1
crmeb/app/adminapi/controller/v1/setting/SystemConfig.php

@@ -48,9 +48,10 @@ class SystemConfig extends AuthController
     {
         $where = $this->request->getMore([
             ['tab_id', 0],
+            ['config_name', ''],
             ['status', -1]
         ]);
-        if (!$where['tab_id']) {
+        if (!$where['tab_id'] && $where['config_name'] == '') {
             return app('json')->fail(100100);
         }
         if ($where['status'] == -1) {
@@ -96,6 +97,8 @@ class SystemConfig extends AuthController
             ['info', ''],
             ['desc', ''],
             ['sort', 0],
+            ['level', 0],
+            ['link_data', []],
             ['status', 0]
         ]);
         if (is_array($data['config_tab_id'])) $data['config_tab_id'] = end($data['config_tab_id']);
@@ -119,6 +122,11 @@ class SystemConfig extends AuthController
             if (!$data['parameter']) return app('json')->fail(400283);
             $this->services->valiDateRadioAndCheckbox($data);
         }
+        if ($data['level'] == 1) {
+            if (!$data['link_data']) return app('json')->fail('请选择关联顶级选项');
+            $data['link_id'] = $data['link_data'][0];
+            $data['link_value'] = $data['link_data'][1];
+        }
         $data['value'] = json_encode($data['value']);
         $config = $this->services->getOne(['menu_name' => $data['menu_name']]);
         if ($config) {
@@ -185,12 +193,19 @@ class SystemConfig extends AuthController
             ['info', ''],
             ['desc', ''],
             ['sort', 0],
+            ['level', 0],
+            ['link_data', []],
             ['status', 0]
         ]);
         if (is_array($data['config_tab_id'])) $data['config_tab_id'] = end($data['config_tab_id']);
         if (!$this->services->get($id)) {
             return app('json')->fail(100026);
         }
+        if ($data['level'] == 1) {
+            if (!$data['link_data']) return app('json')->fail('请选择关联顶级选项');
+            $data['link_id'] = $data['link_data'][0];
+            $data['link_value'] = $data['link_data'][1];
+        }
         $data['value'] = json_encode($data['value']);
         $this->services->update($id, $data);
         CacheService::clear();

+ 169 - 7
crmeb/app/adminapi/controller/v1/setting/SystemCrud.php

@@ -18,6 +18,7 @@ use app\adminapi\controller\AuthController;
 use app\Request;
 use app\services\system\log\SystemFileServices;
 use app\services\system\SystemCrudDataService;
+use app\services\system\SystemCrudListServices;
 use app\services\system\SystemCrudServices;
 use app\services\system\SystemMenusServices;
 use app\services\system\SystemRouteServices;
@@ -116,15 +117,20 @@ class SystemCrud extends AuthController
         $fromField = $searchField = $hasOneField = $columnField = $tableIndex = [];
 
         $dictionaryids = array_column($data['tableField'], 'dictionary_id');
-        if ($dictionaryids) {
-            $dictionaryList = $service->getColumn([['id', 'in', $dictionaryids]], 'value', 'id');
-            foreach ($dictionaryList as &$value) {
-                $value = is_string($value) ? json_decode($value, true) : $value;
-            }
-        } else {
-            $dictionaryList = [];
+        $dictionaryList = [];
+        foreach ($dictionaryids as $dictionaryid) {
+            $dictionaryList[$dictionaryid] = $service->selectList(['cid' => $dictionaryid], 'name as label,value')->toArray();
         }
 
+//        if ($dictionaryids) {
+//            $dictionaryList = $service->getColumn([['id', 'in', $dictionaryids]], 'value', 'id');
+//            foreach ($dictionaryList as &$value) {
+//                $value = is_string($value) ? json_decode($value, true) : $value;
+//            }
+//        } else {
+//            $dictionaryList = [];
+//        }
+
         foreach ($data['tableField'] as $item) {
             //判断字段长度
             if (in_array($item['field_type'], [FormTypeEnum::DATE_TIME, 'timestamp', 'time', 'date', 'year']) && $item['limit'] > 6) {
@@ -926,4 +932,160 @@ class SystemCrud extends AuthController
             return app('json')->fail('删除失败');
         }
     }
+
+
+
+
+    /** 数据字典新 */
+
+    /**
+     * 获取数据字典列表
+     * @param SystemCrudListServices $service
+     * @return Response
+     * @throws \ReflectionException
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/5/20
+     */
+    public function dataDictionaryList(SystemCrudListServices $service)
+    {
+        $where = $this->request->getMore([
+            ['status', ''],
+        ]);
+        return app('json')->success($service->dataDictionaryList($where));
+    }
+
+    /**
+     * 获取数据字典添加修改表单
+     * @param SystemCrudListServices $service
+     * @param $id
+     * @return Response
+     * @throws \FormBuilder\Exception\FormBuilderException
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/5/20
+     */
+    public function dataDictionaryListCreate(SystemCrudListServices $service, $id)
+    {
+        return app('json')->success($service->dataDictionaryListCreate($id));
+    }
+
+    /**
+     * 保存数据字典
+     * @param SystemCrudListServices $service
+     * @param $id
+     * @return Response
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/5/20
+     */
+    public function dataDictionaryListSave(SystemCrudListServices $service, $id)
+    {
+        $data = $this->request->getMore([
+            ['name', ''],
+            ['mark', ''],
+            ['level', ''],
+            ['status', ''],
+        ]);
+        $service->dataDictionaryListSave($id, $data);
+        return app('json')->success('保存成功');
+    }
+
+    /**
+     * 删除数据字典
+     * @param SystemCrudListServices $service
+     * @param $id
+     * @return Response
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/5/20
+     */
+    public function dataDictionaryListDel(SystemCrudListServices $service, $id)
+    {
+        $service->dataDictionaryListDel($id);
+        return app('json')->success('删除成功');
+    }
+
+    /**
+     * 数据字典内容列表
+     * @param SystemCrudDataService $service
+     * @param $cid
+     * @return Response
+     * @throws \ReflectionException
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/5/20
+     */
+    public function dataDictionaryInfoList(SystemCrudDataService $service, $cid)
+    {
+        return app('json')->success($service->dataDictionaryInfoList($cid));
+    }
+
+    /**
+     * 数据字典内容添加修改表单
+     * @param SystemCrudDataService $service
+     * @param $cid
+     * @param $id
+     * @param $pid
+     * @return Response
+     * @throws \FormBuilder\Exception\FormBuilderException
+     * @throws \ReflectionException
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/5/20
+     */
+    public function dataDictionaryInfoCreate(SystemCrudDataService $service, $cid, $id, $pid)
+    {
+        return app('json')->success($service->dataDictionaryInfoCreate($cid, (int)$id, (int)$pid));
+    }
+
+    /**
+     * 保存数据字典内容
+     * @param SystemCrudDataService $service
+     * @param $cid
+     * @param $id
+     * @return Response
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/5/20
+     */
+    public function dataDictionaryInfoSave(SystemCrudDataService $service, $cid, $id)
+    {
+        $data = $this->request->getMore([
+            ['name', ''],
+            ['pid', 0],
+            ['value', ''],
+            ['sort', 0],
+        ]);
+        $service->dataDictionaryInfoSave($cid, $id, $data);
+        return app('json')->success('保存成功');
+    }
+
+    /**
+     * 删除数据字典内容
+     * @param SystemCrudDataService $service
+     * @param $id
+     * @return Response
+     * @throws \ReflectionException
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/5/20
+     */
+    public function dataDictionaryInfoDel(SystemCrudDataService $service, $id)
+    {
+        $service->dataDictionaryInfoDel($id);
+        return app('json')->success('删除成功');
+    }
 }

+ 0 - 74
crmeb/app/adminapi/controller/v1/statistic/FlowStatistic.php

@@ -1,74 +0,0 @@
-<?php
-// +----------------------------------------------------------------------
-// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
-// +----------------------------------------------------------------------
-// | Copyright (c) 2016~2023 https://www.crmeb.com All rights reserved.
-// +----------------------------------------------------------------------
-// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
-// +----------------------------------------------------------------------
-// | Author: CRMEB Team <admin@crmeb.com>
-// +----------------------------------------------------------------------
-
-namespace app\adminapi\controller\v1\statistic;
-
-use app\adminapi\controller\AuthController;
-use app\services\statistic\CapitalFlowServices;
-use think\facade\App;
-
-class FlowStatistic extends AuthController
-{
-    /**
-     * @param App $app
-     * @param CapitalFlowServices $services
-     */
-    public function __construct(App $app, CapitalFlowServices $services)
-    {
-        parent::__construct($app);
-        $this->services = $services;
-    }
-
-    /**
-     * 资金流水
-     * @return mixed
-     */
-    public function getFlowList()
-    {
-        $where = $this->request->getMore([
-            ['time', ''],
-            ['trading_type', 0],
-            ['keywords', ''],
-            ['ids', ''],
-            ['export', 0]
-        ]);
-        $date = $this->services->getFlowList($where);
-        return app('json')->success($date);
-    }
-
-    /**
-     * 资金流水备注
-     * @param $id
-     * @return mixed
-     */
-    public function setMark($id)
-    {
-        $data = $this->request->postMore([
-            ['mark', '']
-        ]);
-        $this->services->setMark($id, $data);
-        return app('json')->success(100024);
-    }
-
-    /**
-     * 账单记录
-     * @return mixed
-     */
-    public function getFlowRecord()
-    {
-        $where = $this->request->getMore([
-            ['type', 'day'],
-            ['time', '']
-        ]);
-        $data = $this->services->getFlowRecord($where);
-        return app('json')->success($data);
-    }
-}

+ 28 - 3
crmeb/app/adminapi/controller/v1/system/AppVersion.php

@@ -36,7 +36,10 @@ class AppVersion extends AuthController
 
     /**
      * 版本列表
-     * @return mixed
+     * @return \think\Response
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/4/2
      */
     public function list()
     {
@@ -48,7 +51,12 @@ class AppVersion extends AuthController
 
     /**
      * 新增版本表单
-     * @return mixed
+     * @param $id
+     * @return \think\Response
+     * @throws \FormBuilder\Exception\FormBuilderException
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/4/2
      */
     public function crate($id)
     {
@@ -57,7 +65,10 @@ class AppVersion extends AuthController
 
     /**
      * 保存数据
-     * @return mixed
+     * @return \think\Response
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/4/2
      */
     public function save()
     {
@@ -75,4 +86,18 @@ class AppVersion extends AuthController
         $this->services->versionSave($id, $data);
         return app('json')->success(100021);
     }
+
+    /**
+     * 删除App版本
+     * @param $id
+     * @return \think\Response
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/4/2
+     */
+    public function del($id)
+    {
+        $this->services->delete($id);
+        return app('json')->success('删除成功');
+    }
 }

+ 54 - 1
crmeb/app/adminapi/controller/v1/system/SystemCrontab.php

@@ -5,6 +5,7 @@ namespace app\adminapi\controller\v1\system;
 use app\adminapi\controller\AuthController;
 use app\services\system\crontab\SystemCrontabServices;
 use think\facade\App;
+use think\facade\Env;
 
 class SystemCrontab extends AuthController
 {
@@ -17,10 +18,16 @@ class SystemCrontab extends AuthController
     /**
      * 获取定时任务列表
      * @return mixed
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
      */
     public function getTimerList()
     {
-        $where = ['is_del' => 0];
+        $where = $this->request->getMore([
+            ['custom', 0],
+        ]);
+        $where['is_del'] = 0;
         return app('json')->success($this->services->getTimerList($where));
     }
 
@@ -28,6 +35,9 @@ class SystemCrontab extends AuthController
      * 获取定时任务详情
      * @param $id
      * @return mixed
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
      */
     public function getTimerInfo($id)
     {
@@ -56,12 +66,24 @@ class SystemCrontab extends AuthController
             ['content', ''],
             ['type', 0],
             ['is_open', 0],
+            ['month', 0],
             ['week', 0],
             ['day', 0],
             ['hour', 0],
             ['minute', 0],
             ['second', 0],
+            ['customCode', ''],
+            ['password', ''],
         ]);
+        if ($data['mark'] == 'customTimer') {
+            if (!Env::get('app_debug', false)) return app('json')->fail('生产环境下无法新增和修改自定义内容,如需修改请修改.env文件中app_debug项为true');
+            if ($data['password'] === '') return app('json')->fail('密码不能为空');
+            if (config('filesystem.password') !== $data['password']) return app('json')->fail('密码错误');
+            $adminInfo = $this->request->adminInfo();
+            if (!$adminInfo) return app('json')->fail('非法操作');
+            if ($adminInfo['level'] != 0) return app('json')->fail('仅超级管理员可以操作定时任务');
+            if (!$this->isSafePhpCode($data['customCode'])) return app('json')->fail('自定义内容存在危险代码,请检查代码');
+        }
         $this->services->saveTimer($data);
         return app('json')->success(100000);
     }
@@ -89,4 +111,35 @@ class SystemCrontab extends AuthController
         return app('json')->success(100014);
     }
 
+    /**
+     * 检查是否包含删除表,删除表数据,删除文件,修改文件内容以及后缀,执行命令等操作的关键词
+     * @param $code
+     * @return bool
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/6/6
+     */
+    function isSafePhpCode($code)
+    {
+        // 检查是否包含删除表,删除表数据,删除文件,修改文件内容以及后缀,执行命令等操作的关键词
+        $dangerous_keywords = array(
+            'delete',
+            'destroy',
+            'DROP TABLE',
+            'DELETE FROM',
+            'unlink(',
+            'fwrite(',
+            'shell_exec(',
+            'exec(',
+            'system(',
+            'passthru('
+        );
+        foreach ($dangerous_keywords as $keyword) {
+            if (strpos($code, $keyword) !== false) {
+                return false;
+            }
+        }
+        return true; // 如果通过所有安全检查,返回 true
+    }
+
 }

+ 9 - 3
crmeb/app/adminapi/controller/v1/system/SystemDatabackup.php

@@ -86,7 +86,9 @@ class SystemDatabackup extends AuthController
      */
     public function optimize()
     {
-        $tables = $this->request->param('tables', '', 'htmlspecialchars');
+        [$tables] = $this->request->postMore([
+            ['tables', ''],
+        ], true);
         $res = $this->services->getDbBackup()->optimize($tables);
         return app('json')->success($res ? 100047 : 100048);
     }
@@ -96,7 +98,9 @@ class SystemDatabackup extends AuthController
      */
     public function repair()
     {
-        $tables = $this->request->param('tables', '', 'htmlspecialchars');
+        [$tables] = $this->request->postMore([
+            ['tables', ''],
+        ], true);
         $res = $this->services->getDbBackup()->repair($tables);
         return app('json')->success($res ? 100049 : 100050);
     }
@@ -106,7 +110,9 @@ class SystemDatabackup extends AuthController
      */
     public function backup()
     {
-        $tables = $this->request->param('tables', '', 'htmlspecialchars');
+        [$tables] = $this->request->postMore([
+            ['tables', ''],
+        ], true);
         $data = $this->services->backup($tables);
         return app('json')->success(100051);
     }

+ 157 - 0
crmeb/app/adminapi/controller/v1/system/SystemEvent.php

@@ -0,0 +1,157 @@
+<?php
+
+namespace app\adminapi\controller\v1\system;
+
+use app\adminapi\controller\AuthController;
+use app\services\system\SystemEventServices;
+use think\facade\App;
+use think\facade\Env;
+
+class SystemEvent extends AuthController
+{
+    public function __construct(App $app, SystemEventServices $services)
+    {
+        parent::__construct($app);
+        $this->services = $services;
+    }
+
+    /**
+     * 自定事件类型
+     * @return \think\Response
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/6/7
+     */
+    public function getMarkList()
+    {
+        return app('json')->success($this->services->getMarkList());
+    }
+
+    /**
+     * 自定事件列表
+     * @return \think\Response
+     * @throws \ReflectionException
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/6/7
+     */
+    public function getEventList()
+    {
+        return app('json')->success($this->services->getEventList());
+    }
+
+    /**
+     * 自定事件详情
+     * @param $id
+     * @return \think\Response
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/6/7
+     */
+    public function getEventInfo($id)
+    {
+        if (!$id) return app('json')->fail('参数错误');
+        return app('json')->success($this->services->getEventInfo($id));
+    }
+
+    /**
+     * 自定事件添加编辑
+     * @return \think\Response
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/6/7
+     */
+    public function saveEvent()
+    {
+        $data = $this->request->postMore([
+            ['id', 0],
+            ['name', ''],
+            ['mark', ''],
+            ['content', ''],
+            ['is_open', 0],
+            ['customCode', ''],
+            ['password', ''],
+        ]);
+        if ($data['name'] == '') return app('json')->fail('请填写事件名称');
+        if ($data['mark'] == '') return app('json')->fail('请选择事件类型');
+        if (!Env::get('app_debug', false)) return app('json')->fail('生产环境下无法新增和修改自定义内容,如需修改请修改.env文件中app_debug项为true');
+        if ($data['password'] === '') return app('json')->fail('密码不能为空');
+        if (config('filesystem.password') !== $data['password']) return app('json')->fail('密码错误');
+        $adminInfo = $this->request->adminInfo();
+        if (!$adminInfo) return app('json')->fail('非法操作');
+        if ($adminInfo['level'] != 0) return app('json')->fail('仅超级管理员可以操作定时任务');
+        if (!$this->isSafePhpCode($data['customCode'])) return app('json')->fail('自定义内容存在危险代码,请检查代码');
+        $this->services->saveEvent($data);
+        return app('json')->success(100000);
+    }
+
+    /**
+     * 检查是否包含删除表,删除表数据,删除文件,修改文件内容以及后缀,执行命令等操作的关键词
+     * @param $code
+     * @return bool
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/6/7
+     */
+    function isSafePhpCode($code)
+    {
+        // 检查是否包含删除表,删除表数据,删除文件,修改文件内容以及后缀,执行命令等操作的关键词
+        $dangerous_keywords = [
+            'delete',
+            'destroy',
+            'DROP TABLE',
+            'DELETE FROM',
+            'unlink(',
+            'fwrite(',
+            'shell_exec(',
+            'exec(',
+            'system(',
+            'passthru('
+        ];
+        foreach ($dangerous_keywords as $keyword) {
+            if (strpos($code, $keyword) !== false) {
+                return false;
+            }
+        }
+        return true; // 如果通过所有安全检查,返回 true
+    }
+
+    /**
+     * 自定事件是否开启开关
+     * @param $id
+     * @param $is_open
+     * @return \think\Response
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/6/7
+     */
+    public function setEventStatus($id, $is_open)
+    {
+        $this->services->setEventStatus($id, $is_open);
+        return app('json')->success(100014);
+    }
+
+    /**
+     * 删除自定事件
+     * @param $id
+     * @return \think\Response
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/6/7
+     */
+    public function delEvent($id)
+    {
+        if (!$id) return app('json')->fail('参数错误');
+        $this->services->eventDel($id);
+        return app('json')->success(100002);
+    }
+}

+ 16 - 0
crmeb/app/adminapi/route/order.php

@@ -94,6 +94,22 @@ Route::group('order', function () {
     Route::post('invoice/set/:id', 'v1.order.StoreOrderInvoice/set_invoice')->name('StoreOrderorInvoiceSet')->option(['real_name' => '设置发票状态']);
     //开票订单详情
     Route::get('invoice_order_info/:id', 'v1.order.StoreOrderInvoice/orderInfo')->name('StoreOrderorInvoiceOrderInfo')->option(['real_name' => '开票订单详情']);
+    //获取发票开具页面iframe地址
+    Route::get('invoice_issuance_url/:id', 'v1.order.StoreOrderInvoice/invoiceIssuanceUrl')->name('invoiceIssuanceUrl')->option(['real_name' => '获取发票开具页面iframe地址']);
+    //保存发票信息
+    Route::post('save_invoice_info/:id', 'v1.order.StoreOrderInvoice/saveInvoiceInfo')->name('saveInvoiceInfo')->option(['real_name' => '保存发票信息']);
+    //电子发票分类
+    Route::get('invoice_category', 'v1.order.StoreOrderInvoice/invoiceCategory')->name('invoiceCategory')->option(['real_name' => '电子发票分类']);
+    //开具发票
+    Route::post('invoice_issuance', 'v1.order.StoreOrderInvoice/invoiceIssuance')->name('invoiceIssuance')->option(['real_name' => '开具发票']);
+    //查看发票详情
+    Route::get('invoice_info/:id', 'v1.order.StoreOrderInvoice/invoiceInfo')->name('invoiceInfo')->option(['real_name' => '查看发票详情']);
+    //开具负数发票
+    Route::get('red_invoice_issuance/:id', 'v1.order.StoreOrderInvoice/redInvoiceIssuance')->name('redInvoiceIssuance')->option(['real_name' => '开具负数发票']);
+    //下载发票
+    Route::get('down_invoice/:id', 'v1.order.StoreOrderInvoice/downInvoice')->name('downInvoice')->option(['real_name' => '下载发票']);
+    //电子发票配置
+    Route::get('elec_invoice_config', 'v1.order.StoreOrderInvoice/elecInvoiceConfig')->name('elecInvoiceConfig')->option(['real_name' => '电子发票配置']);
     //配送员列表
     Route::get('delivery/index', 'v1.order.DeliveryService/index')->option(['real_name' => '配送员列表']);
     //新增配送表单

+ 2 - 0
crmeb/app/adminapi/route/product.php

@@ -99,6 +99,8 @@ Route::group('product', function () {
         Route::get('reply/fictitious_reply/:product_id', 'v1.product.StoreProductReply/fictitious_reply')->option(['real_name' => '虚拟评论表单']);
         //保存虚拟评论
         Route::post('reply/save_fictitious_reply', 'v1.product.StoreProductReply/save_fictitious_reply')->option(['real_name' => '保存虚拟评论']);
+        //审核商品评论
+        Route::put('reply/set_status/:id/:status', 'v1.product.StoreProductReply/set_status')->option(['real_name' => '审核商品评论']);
     })->option(['parent' => 'product', 'cate_name' => '商品评论']);
 
     /** 商品采集 */

+ 37 - 1
crmeb/app/adminapi/route/system.php

@@ -94,7 +94,9 @@ Route::group('system', function () {
         //添加版本信息
         Route::get('version_crate/:id', 'v1.system.AppVersion/crate')->option(['real_name' => '添加版本']);
         //添加版本信息
-        Route::post('version_save', 'v1.system.AppVersion/save')->option(['real_name' => '添加版本']);
+        Route::post('version_save', 'v1.system.AppVersion/save')->option(['real_name' => '保存版本']);
+        //删除版本信息
+        Route::delete('version_del/:id', 'v1.system.AppVersion/del')->option(['real_name' => '删除版本']);
     })->option(['parent' => 'system', 'cate_name' => '数据清除']);
 
     /** 在线升级 */
@@ -135,6 +137,22 @@ Route::group('system', function () {
         Route::get('crontab/set_open/:id/:is_open', 'v1.system.SystemCrontab/setTimerStatus')->option(['real_name' => '定时任务是否开启开关']);
     })->option(['parent' => 'system', 'cate_name' => '定时任务']);
 
+    /** 自定事件 */
+    Route::group(function () {
+        //定时任务列表
+        Route::get('event/list', 'v1.system.SystemEvent/getEventList')->option(['real_name' => '自定事件列表']);
+        //定时任务类型
+        Route::get('event/mark', 'v1.system.SystemEvent/getMarkList')->option(['real_name' => '自定事件类型']);
+        //定时任务详情
+        Route::get('event/info/:id', 'v1.system.SystemEvent/getEventInfo')->option(['real_name' => '自定事件详情']);
+        //定时任务添加编辑
+        Route::post('event/save', 'v1.system.SystemEvent/saveEvent')->option(['real_name' => '自定事件添加编辑']);
+        //删除定时任务
+        Route::delete('event/del/:id', 'v1.system.SystemEvent/delEvent')->option(['real_name' => '删除自定事件']);
+        //定时任务是否开启开关
+        Route::get('event/set_open/:id/:is_open', 'v1.system.SystemEvent/setEventStatus')->option(['real_name' => '自定事件是否开启开关']);
+    })->option(['parent' => 'system', 'cate_name' => '自定事件']);
+
     /** 系统路由 */
     Route::group(function () {
         //同步路由接口
@@ -174,6 +192,24 @@ Route::group('system', function () {
         Route::get('crud/menus', 'v1.setting.SystemCrud/getMenus')->option(['real_name' => '获取菜单TREE形数据']);
         //获取CRUD文件存放
         Route::post('crud/file_path', 'v1.setting.SystemCrud/getFilePath')->option(['real_name' => '获取CRUD文件存放']);
+
+        //获取数据字典列表
+        Route::get('crud/data_dictionary_list', 'v1.setting.SystemCrud/dataDictionaryList')->option(['real_name' => '获取数据字典列表']);
+        //获取数据字典添加修改表单
+        Route::get('crud/data_dictionary_list/create/:id', 'v1.setting.SystemCrud/dataDictionaryListCreate')->option(['real_name' => '获取数据字典添加修改表单']);
+        //保存数据字典
+        Route::post('crud/data_dictionary_list/save/:id', 'v1.setting.SystemCrud/dataDictionaryListSave')->option(['real_name' => '保存数据字典']);
+        //删除数据字典
+        Route::delete('crud/data_dictionary_list/del/:id', 'v1.setting.SystemCrud/dataDictionaryListDel')->option(['real_name' => '删除数据字典']);
+        //查看数据字典内容列表
+        Route::get('crud/data_dictionary/info_list/:cid', 'v1.setting.SystemCrud/dataDictionaryInfoList')->option(['real_name' => '查看数据字典内容列表']);
+        //查看数据字典内容添加修改表单
+        Route::get('crud/data_dictionary/info_create/:cid/:id/:pid', 'v1.setting.SystemCrud/dataDictionaryInfoCreate')->option(['real_name' => '查看数据字典内容添加修改表单']);
+        //修改或者保存字典数据内容
+        Route::post('crud/data_dictionary/info_save/:cid/:id', 'v1.setting.SystemCrud/dataDictionaryInfoSave')->option(['real_name' => '修改或者保存字典数据内容']);
+        //删除数据字典内容
+        Route::delete('crud/data_dictionary/info_del/:id', 'v1.setting.SystemCrud/dataDictionaryInfoDel')->option(['real_name' => '删除数据字典内容']);
+
         //获取数据字典列表
         Route::get('crud/data_dictionary', 'v1.setting.SystemCrud/getDataDictionary')->option(['real_name' => '获取数据字典列表']);
         //查看数据字典

+ 1 - 1
crmeb/app/api/controller/pc/ProductController.php

@@ -43,7 +43,7 @@ class ProductController
             [['news', 'd'], 0, '', 'timeOrder'],
             [['type', 0], 0],
             ['ids', ''],
-            ['selectId', '']
+            [['selectId', 'd'], 0]
         ]);
         if ($where['selectId'] && (!$where['sid'] || !$where['cid'])) {
             if ($services->value(['id' => $where['selectId']], 'pid')) {

+ 72 - 0
crmeb/app/api/controller/pc/PublicController.php

@@ -13,7 +13,10 @@ namespace app\api\controller\pc;
 
 
 use app\Request;
+use app\services\article\ArticleCategoryServices;
+use app\services\article\ArticleServices;
 use app\services\pc\PublicServices;
+use crmeb\services\CacheService;
 
 class PublicController
 {
@@ -53,6 +56,8 @@ class PublicController
         $data['network_security'] = sys_config('network_security');
         $data['network_security_url'] = sys_config('network_security_url');
         $data['icp_url'] = sys_config('icp_url');
+        $data['pc_home_menus'] = sys_data('pc_home_menus');
+        $data['pc_home_links'] = sys_data('pc_home_links');
         $logoUrl = sys_config('pc_logo');
         if (strstr($logoUrl, 'http') === false && $logoUrl) {
             $logoUrl = sys_config('site_url') . $logoUrl;
@@ -71,4 +76,71 @@ class PublicController
         $data['wechat_qrcode'] = sys_config('wechat_qrcode');
         return app('json')->success($data);
     }
+
+    /**
+     * 文章分类
+     * @param ArticleCategoryServices $services
+     * @return \think\Response
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/5/6
+     */
+    public function getNewsCategory(ArticleCategoryServices $services)
+    {
+        $cateInfo = CacheService::remember('ARTICLE_CATEGORY_PC', function () use ($services) {
+            return $services->getArticleCategory();
+        });
+        return app('json')->success($cateInfo);
+    }
+
+    /**
+     * pc文章列表
+     * @param Request $request
+     * @param ArticleServices $services
+     * @return \think\Response
+     * @throws \ReflectionException
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/5/6
+     */
+    public function getNewsList(Request $request, ArticleServices $services)
+    {
+        list($cid, $page, $limit) = $request->getMore([
+            [['cid', 'd'], 0],
+            [['page', 'd'], 0],
+            [['limit', 'd'], 0],
+        ], true);
+        if ($cid == 0) {
+            $where = ['is_hot' => 1];
+        } else {
+            $where = ['cid' => $cid];
+        }
+        $data = $services->getList($where, $page, $limit);
+        foreach ($data['list'] as &$item) {
+            $item['add_time'] = date('Y-m-d H:i', $item['add_time']);
+        }
+        return app('json')->success($data);
+    }
+
+    /**
+     * 文章详情
+     * @param ArticleServices $services
+     * @param $id
+     * @return \think\Response
+     * @throws \ReflectionException
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/5/6
+     */
+    public function getNewsDetail(ArticleServices $services, $id)
+    {
+        $info = $services->getInfo($id);
+        return app('json')->success($info);
+    }
 }

+ 1 - 1
crmeb/app/api/controller/v1/CrontabController.php

@@ -28,7 +28,7 @@ class CrontabController
      */
     public function crontabRun()
     {
-        app()->make(SystemCrontabServices::class)->crontabRun();
+        app()->make(SystemCrontabServices::class)->crontabApiRun();
     }
 
     /**

+ 21 - 0
crmeb/app/api/controller/v1/LoginController.php

@@ -529,4 +529,25 @@ class LoginController
             return app('json')->fail(400336);
         }
     }
+
+    /**
+     * 远程登录接口
+     * @param Request $request
+     * @return \think\Response
+     * @throws \Psr\SimpleCache\InvalidArgumentException
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/5/21
+     */
+    public function remoteRegister(Request $request)
+    {
+        [$remote_token] = $request->getMore([
+            ['remote_token', ''],
+        ], true);
+        if ($remote_token == '') return app('json')->success('登录失败', ['get_remote_login_url' => sys_config('get_remote_login_url')]);
+        return app('json')->success('登录成功', $this->services->remoteRegister($remote_token));
+    }
 }

+ 30 - 0
crmeb/app/api/controller/v1/PublicController.php

@@ -15,6 +15,8 @@ use app\services\activity\combination\StorePinkServices;
 use app\services\diy\DiyServices;
 use app\services\kefu\service\StoreServiceServices;
 use app\services\order\DeliveryServiceServices;
+use app\services\order\StoreOrderCartInfoServices;
+use app\services\order\StoreOrderServices;
 use app\services\other\AgreementServices;
 use app\services\other\CacheServices;
 use app\services\product\product\StoreCategoryServices;
@@ -716,4 +718,32 @@ class PublicController
             echo '<h1>未找到跳转路径</h1>';
         }
     }
+
+    /**
+     * 微信服务商支付
+     * @param Request $request
+     * @return \think\Response
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/4/7
+     */
+    public function servicePayResult(Request $request)
+    {
+        [$sub_mch_id, $out_trade_no, $check_code] = $request->getMore([
+            ['sub_mch_id', ''],
+            ['out_trade_no', ''],
+            ['check_code', ''],
+        ], true);
+        $data['site_name'] = sys_config('site_name');//网站名称
+        $data['site_url'] = sys_config('site_url');//网站地址
+        $data['site_logo'] = sys_config('wap_login_logo');//移动端登录logo
+        $order = app()->make(StoreOrderServices::class)->getOne(['order_id' => $out_trade_no]);
+        $data['goods_name'] = app()->make(StoreOrderCartInfoServices::class)->getCarIdByProductTitle((int)$order['id']);
+        $data['pay_price'] = $order['pay_price'];
+        $data['jump_url'] = sys_config('site_url') . '/pages/goods/order_pay_status/index?order_id=' . $out_trade_no . '&msg=支付成功&type=3&totalPrice=' . $data['pay_price'];
+        return app('json')->header(['X-Frame-Options' => 'payapp.weixin.qq.com'])->success($data);
+    }
 }

+ 1 - 1
crmeb/app/api/controller/v1/activity/StoreBargainController.php

@@ -134,7 +134,7 @@ class StoreBargainController
         ], true);
         /** @var StoreBargainUserServices $bargainUser */
         $bargainUser = app()->make(StoreBargainUserServices::class);
-        $bargainUserTableId = $bargainUser->getBargainUserTableId($bargainId, $bargainUserUid);
+        $bargainUserTableId = $bargainUser->getBargainUserTableId((int)$bargainId, (int)$bargainUserUid);
 
         /** @var StoreBargainUserHelpServices $bargainUserHelp */
         $bargainUserHelp = app()->make(StoreBargainUserHelpServices::class);

+ 1 - 1
crmeb/app/api/controller/v1/order/OtherOrderController.php

@@ -120,7 +120,7 @@ class OtherOrderController
             //创建订单jspay支付
             $payPriceStatus = $OtherOrderServices->zeroYuanPayment($orderInfo);
             if ($payPriceStatus)//0元支付成功
-                return app('json')->status('success', 410199, $info);
+                return app('json')->status('success', 410217, $info);
             else
                 return app('json')->status('pay_error');
         }

+ 35 - 5
crmeb/app/api/controller/v1/order/StoreOrderController.php

@@ -18,12 +18,12 @@ use app\services\activity\{lottery\LuckLotteryServices,
     combination\StorePinkServices
 };
 use app\services\activity\coupon\StoreCouponIssueServices;
-use app\services\order\{
-    StoreCartServices,
+use app\services\order\{StoreCartServices,
     StoreOrderCartInfoServices,
     StoreOrderComputedServices,
     StoreOrderCreateServices,
     StoreOrderEconomizeServices,
+    StoreOrderInvoiceServices,
     StoreOrderRefundServices,
     StoreOrderServices,
     StoreOrderStatusServices,
@@ -269,7 +269,7 @@ class StoreOrderController
             $success = app()->make(StoreOrderSuccessServices::class);
             $payPriceStatus = $success->zeroYuanPayment($orderInfo, $uid, $paytype);
             if ($payPriceStatus)//0元支付成功
-                return app('json')->status('success', 410195, ['order_id' => $orderInfo['order_id'], 'key' => $orderInfo['unique']]);
+                return app('json')->status('success', '支付成功', ['order_id' => $orderInfo['order_id'], 'key' => $orderInfo['unique']]);
             else
                 return app('json')->status('pay_error', 410216);
         }
@@ -571,6 +571,17 @@ class StoreOrderController
         if (!$res) {
             return app('json')->fail(410222);
         }
+
+        //自定义事件-订单评价
+        event('CustomEventListener', ['order_comment', [
+            'uid' => $uid,
+            'oid' => $cartInfo['oid'],
+            'unique' => $unique,
+            'product_id' => $productId,
+            'add_time' => date('Y-m-d H:i:s'),
+            'suk' => $cartInfo['cart_info']['productInfo']['attrInfo']['suk']
+        ]]);
+
         try {
             $this->services->checkOrderOver($replyServices, $cartInfoServices->getCartColunm(['oid' => $cartInfo['oid']], 'unique', ''), $cartInfo['oid']);
         } catch (\Exception $e) {
@@ -807,6 +818,9 @@ class StoreOrderController
         ]);
         $data['data'] = $this->decrypt($data['data'], sys_config('sms_token'));
         switch ($data['type']) {
+            case 'detection'://检测回调地址
+                return \json($data['data']);
+                break;
             case 'order_success'://下单成功
                 $update = [
                     'label' => $data['data']['label'] ?? '',
@@ -872,7 +886,23 @@ class StoreOrderController
                         ]);
                     }
                 }
-
+                break;
+            case 'success'://电子发票回调
+                $oid = $this->services->value(['order_id' => $data['data']['unique']], 'id');
+                if ($oid) {
+                    $invoiceServices = app()->make(StoreOrderInvoiceServices::class);
+                    $invoiceServices->update([
+                        'category' => 'order',
+                        'order_id' => $oid,
+                    ], [
+                        'unique' => $data['data']['unique'],
+                        'invoice_type' => $data['data']['invoice_type'],
+                        'invoice_num' => $data['data']['invoice_num'],
+                        'invoice_serial_number' => $data['data']['invoice_serial_number'],
+                        'is_invoice' => 1,
+                        'invoice_time' => time()
+                    ]);
+                }
                 break;
         }
 
@@ -895,6 +925,6 @@ class StoreOrderController
         $iv = substr($decodedData, 0, 16);
         $encrypted = substr($decodedData, 16);
         $decrypted = openssl_decrypt($encrypted, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
-        return $decrypted;
+        return json_decode($decrypted, true);
     }
 }

+ 12 - 0
crmeb/app/api/controller/v1/order/StoreOrderRefundController.php

@@ -75,6 +75,18 @@ class StoreOrderRefundController
         }
         $this->services->update($orderRefund['id'], ['is_cancel' => 1]);
         $this->services->cancelOrderRefundCartInfo((int)$orderRefund['id'], (int)$orderRefund['store_order_id'], $orderRefund);
+
+        //自定义事件-用户取消退款
+        event('CustomEventListener', ['order_refund_cancel', [
+            'uid' => $orderRefund['uid'],
+            'id' => $orderRefund['id'],
+            'store_order_id' => $orderRefund['store_order_id'],
+            'order_id' => $orderRefund['order_id'],
+            'refund_num' => $orderRefund['refund_num'],
+            'refund_price' => $orderRefund['refund_price'],
+            'cancel_time' => date('Y-m-d H:i:s'),
+        ]]);
+
         return app('json')->success(100019);
     }
 

+ 36 - 4
crmeb/app/api/controller/v1/publics/ArticleController.php

@@ -30,6 +30,10 @@ class ArticleController
      * 文章列表
      * @param $cid
      * @return mixed
+     * @throws \ReflectionException
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
      */
     public function lst($cid)
     {
@@ -39,7 +43,10 @@ class ArticleController
             $where = ['cid' => $cid];
         }
         [$page, $limit] = $this->services->getPageValue();
-        $list = $this->services->cidByArticleList($where, $page, $limit, "id,title,image_input,visit,from_unixtime(add_time,'%Y-%m-%d %H:%i') as add_time,synopsis,url");
+        $list = $this->services->getList($where, $page, $limit)['list'];
+        foreach ($list as &$item){
+            $item['add_time'] = date('Y-m-d H:i', $item['add_time']);
+        }
         return app('json')->success($list);
     }
 
@@ -47,6 +54,10 @@ class ArticleController
      * 文章详情
      * @param $id
      * @return mixed
+     * @throws \ReflectionException
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
      */
     public function details($id)
     {
@@ -57,32 +68,53 @@ class ArticleController
     /**
      * 获取热门文章
      * @return mixed
+     * @throws \ReflectionException
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
      */
     public function hot()
     {
         [$page, $limit] = $this->services->getPageValue();
-        $list = $this->services->cidByArticleList(['is_hot' => 1], $page, $limit, "id,title,image_input,visit,from_unixtime(add_time,'%Y-%m-%d %H:%i') as add_time,synopsis,url");
+        $list = $this->services->getList(['is_hot' => 1], $page, $limit)['list'];
+        foreach ($list as &$item){
+            $item['add_time'] = date('Y-m-d H:i', $item['add_time']);
+        }
         return app('json')->success($list);
     }
 
     /**
      * @return mixed
+     * @throws \ReflectionException
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
      */
     public function new()
     {
         [$page, $limit] = $this->services->getPageValue();
-        $list = $this->services->cidByArticleList([], $page, $limit, "id,title,image_input,visit,from_unixtime(add_time,'%Y-%m-%d %H:%i') as add_time,synopsis,url");
+        $list = $this->services->getList([], $page, $limit)['list'];
+        foreach ($list as &$item){
+            $item['add_time'] = date('Y-m-d H:i', $item['add_time']);
+        }
         return app('json')->success($list);
     }
 
     /**
      * 获取顶部banner文章
      * @return mixed
+     * @throws \ReflectionException
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
      */
     public function banner()
     {
         [$page, $limit] = $this->services->getPageValue();
-        $list = $this->services->cidByArticleList(['is_banner' => 1], $page, $limit, "id,title,image_input,visit,from_unixtime(add_time,'%Y-%m-%d %H:%i') as add_time,synopsis,url");
+        $list = $this->services->getList(['is_banner' => 1], $page, $limit)['list'];
+        foreach ($list as &$item){
+            $item['add_time'] = date('Y-m-d H:i', $item['add_time']);
+        }
         return app('json')->success($list);
     }
 }

+ 9 - 4
crmeb/app/api/controller/v1/store/StoreProductController.php

@@ -57,9 +57,9 @@ class StoreProductController
             [['news', 'd'], 0, '', 'is_new'],
             [['type', 0], 0],
             ['ids', ''],
-            ['selectId', ''],
-            ['productId', ''],
-            ['coupon_category_id', '']
+            [['selectId', 'd'], 0],
+            [['productId', 'd'], 0],
+            [['coupon_category_id', 'd'], 0],
         ]);
         if ($where['selectId'] && (!$where['sid'] || !$where['cid'])) {
             if ($services->value(['id' => $where['selectId']], 'pid')) {
@@ -92,7 +92,12 @@ class StoreProductController
      */
     public function code(Request $request, $id)
     {
-        $code = $this->services->getCode((int)$id, $request->get('user_type', 'wechat'), $request->user());
+        if ($request->uid()) {
+            $user = $request->user();
+        } else {
+            $user = ['uid' => 0, 'is_promoter' => 0];
+        }
+        $code = $this->services->getCode((int)$id, $request->get('user_type', 'wechat'), $user);
         return app('json')->success(['code' => $code]);
     }
 

+ 8 - 1
crmeb/app/api/controller/v1/user/DivisionController.php

@@ -139,6 +139,9 @@ class DivisionController
      * 绑定员工方法
      * @param Request $request
      * @return \think\Response
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
      * @author 吴汐
      * @email 442384644@qq.com
      * @date 2024/2/2
@@ -150,6 +153,10 @@ class DivisionController
             ['agent_code', 0],
         ], true);
         $res = app()->make(DivisionServices::class)->agentSpreadStaff($request->uid(), (int)$agentId, (int)$agentCode);
-        return app('json')->success($res);
+        if ($res) {
+            return app('json')->success($res);
+        } else {
+            return app('json')->fail('无操作');
+        }
     }
 }

+ 4 - 1
crmeb/app/api/controller/v1/user/UserAddressController.php

@@ -39,10 +39,13 @@ class UserAddressController
      */
     public function address(Request $request, $id)
     {
+        $uid = (int)$request->uid();
         if (!$id) {
             return app('json')->fail(100100);
         }
-        return app('json')->success($this->services->address((int)$id));
+        $info = $this->services->address((int)$id);
+        if ($info['uid'] != $uid) return app('json')->fail(100026);
+        return app('json')->success($info);
     }
 
     /**

+ 3 - 0
crmeb/app/api/controller/v1/user/UserSignController.php

@@ -73,6 +73,9 @@ class UserSignController
      */
     public function sign_integral(Request $request)
     {
+        if (sys_config('sign_status') == 0) {
+            return app('json')->fail('签到功能未开启');
+        }
         $uid = (int)$request->uid();
         $integral = $this->services->sign($uid);
         return app('json')->success(410127, ['integral' => $integral], ['integral' => $integral]);

+ 16 - 0
crmeb/app/api/controller/v2/order/StoreOrderInvoiceController.php

@@ -15,6 +15,7 @@ namespace app\api\controller\v2\order;
 use app\services\order\StoreOrderInvoiceServices;
 use app\services\order\StoreOrderServices;
 use app\services\other\PosterServices;
+use app\services\serve\ServeServices;
 use app\services\system\attachment\SystemAttachmentServices;
 use app\services\system\store\SystemStoreServices;
 use think\Request;
@@ -118,4 +119,19 @@ class StoreOrderInvoiceController
         $order['ali_pay_status'] = (bool)sys_config('ali_pay_status');//支付宝支付 1 开启 0 关闭
         return app('json')->success($services->tidyOrder($order, true, true));
     }
+
+    /**
+     * 前端下载电子发票
+     * @param $id
+     * @return \think\Response
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/5/14
+     */
+    public function downInvoice($id)
+    {
+        $info = $this->services->getOne(['id' => $id]);
+        $invoice = app()->make(ServeServices::class)->invoice();
+        return app('json')->success($invoice->downloadInvoice($info['invoice_num']));
+    }
 }

+ 3 - 0
crmeb/app/api/route/pc.php

@@ -37,6 +37,9 @@ Route::group('pc', function () {
         Route::get('get_recommend/:type', 'pc.ProductController/getRecommendList')->name('getRecommendList')->option(['real_name' => '获取推荐商品']);//获取推荐商品
         Route::get('get_wechat_qrcode', 'pc.PublicController/getWechatQrcode')->name('getWechatQrcode')->option(['real_name' => '获取关注二维码']);//获取关注二维码
         Route::get('get_good_product', 'pc.ProductController/getGoodProduct')->name('getGoodProduct')->option(['real_name' => '获取优品推荐']);//获取优品推荐
+        Route::get('get_news_category', 'pc.PublicController/getNewsCategory')->name('getNewsCategory')->option(['real_name' => '获取文章分类']);//获取文章分类
+        Route::get('get_news_list', 'pc.PublicController/getNewsList')->name('getNewsList')->option(['real_name' => '获取文章列表']);//获取文章列表
+        Route::get('get_news_detail/:id', 'pc.PublicController/getNewsDetail')->name('getNewsDetail')->option(['real_name' => '获取文章详情']);//获取文章详情
     })->middleware(\app\http\middleware\AllowOriginMiddleware::class)
         ->middleware(\app\api\middleware\StationOpenMiddleware::class)
         ->middleware(\app\api\middleware\AuthTokenMiddleware::class, false)

+ 4 - 3
crmeb/app/api/route/v1.php

@@ -21,6 +21,7 @@ Route::group(function () {
     Route::any('order_call_back', 'v1.order.StoreOrderController/callBack')->option(['real_name' => '商家寄件回调']);//商家寄件回调
     Route::get('get_script', 'v1.PublicController/getScript')->option(['real_name' => '获取统计代码']);//获取统计代码
     Route::get('version', 'v1.PublicController/getVersion')->option(['real_name' => '获取代码版本号']);
+    Route::get('service_pay_result', 'v1.PublicController/servicePayResult')->option(['real_name' => '服务商支付商家小票接口']);
 })->middleware(\app\http\middleware\AllowOriginMiddleware::class)->option(['mark' => 'serve', 'mark_name' => '服务接口']);
 
 Route::group(function () {
@@ -54,6 +55,8 @@ Route::group(function () {
     Route::get('basic_config', 'v1.PublicController/getMallBasicConfig')->option(['real_name' => '商城基础配置汇总接口']);
     //小程序跳转url接口
     Route::get('get_scheme_url/:id', 'v1.PublicController/getSchemeUrl')->option(['real_name' => '小程序跳转url接口']);
+    //远程注册用户
+    Route::get('remote_register', 'v1.LoginController/remoteRegister')->option(['real_name' => '远程注册用户']);
 
 })->middleware(\app\http\middleware\AllowOriginMiddleware::class)
     ->middleware(\app\api\middleware\StationOpenMiddleware::class)
@@ -104,9 +107,6 @@ Route::group(function () {
         Route::post('user/binding', 'v1.LoginController/user_binding_phone')->name('userBindingPhone')->option(['real_name' => '用户绑定手机号']);
         Route::get('logout', 'v1.LoginController/logout')->name('logout')->option(['real_name' => '退出登录']);// 退出登录
         Route::post('switch_h5', 'v1.LoginController/switch_h5')->name('switch_h5')->option(['real_name' => '切换账号']);// 切换账号
-        //商品类
-        Route::get('product/code/:id', 'v1.store.StoreProductController/code')->name('productCode')->option(['real_name' => '商品分享二维码']);//商品分享二维码 推广员
-
         //公共类
         Route::post('upload/image', 'v1.PublicController/upload_image')->name('uploadImage')->option(['real_name' => '图片上传']);//图片上传
     })->option(['mark' => 'common', 'mark_name' => '公共接口']);
@@ -366,6 +366,7 @@ Route::group(function () {
         Route::get('reply/list/:id', 'v1.store.StoreProductController/reply_list')->name('replyList')->option(['real_name' => '商品评价列表']);//商品评价列表
         Route::get('reply/config/:id', 'v1.store.StoreProductController/reply_config')->name('replyConfig')->option(['real_name' => '商品评价数量和好评度']);//商品评价数量和好评度
         Route::get('advance/list', 'v1.store.StoreProductController/advanceList')->name('advanceList')->option(['real_name' => '预售商品列表']);//预售商品列表
+        Route::get('product/code/:id', 'v1.store.StoreProductController/code')->name('productCode')->option(['real_name' => '商品分享二维码']);//商品分享二维码 推广员
     })->option(['mark' => 'product', 'mark_name' => '商品']);
 
     Route::group(function () {

+ 2 - 0
crmeb/app/api/route/v2.php

@@ -76,6 +76,8 @@ Route::group('v2', function () {
             Route::get('order/invoice_list', 'v2.order.StoreOrderInvoiceController/list')->name('orderInvoiceList')->option(['real_name' => '订单申请开票记录']);
             //订单开票详情
             Route::get('order/invoice_detail/:uni', 'v2.order.StoreOrderInvoiceController/detail')->name('orderInvoiceList')->option(['real_name' => '订单开票详情']);
+            //下载电子发票
+            Route::get('order/down_invoice/:id', 'v2.order.StoreOrderInvoiceController/downInvoice')->name('downInvoice')->option(['real_name' => '下载电子发票']);
         })->option(['mark' => 'invoice', 'mark_name' => '发票']);
 
         //清除搜索记录

+ 45 - 2
crmeb/app/common.php

@@ -120,7 +120,7 @@ if (!function_exists('sys_config')) {
 
 if (!function_exists('sys_data')) {
     /**
-     * 获取系统单个配置
+     * 获取系统单个数据
      * @param string $name
      * @return string
      */
@@ -615,6 +615,49 @@ if (!function_exists('sql_filter')) {
     }
 }
 
+if (!function_exists('filter_str')) {
+    /**
+     * 过滤字符串敏感字符
+     * @param $str
+     * @return array|mixed|string|string[]|null
+     */
+    function filter_str($str)
+    {
+        $rules = [
+            '/\.\./', // 禁用包含 ../ 的参数
+            '/\<\?/', // 禁止 php 脚本出现
+            '/\bor\b.*=.*/i', // 匹配 'or 1=1',防止 SQL 注入(注意边界词 \b 和不区分大小写 i 修饰符)
+            '/(select[\s\S]*?)(from|limit)/i', // 防止 SQL 注入
+            '/(union[\s\S]*?select)/i', // 防止 SQL 注入
+            '/(having|updatexml|extractvalue)/i', // 防止 SQL 注入
+            '/sleep\((\s*)(\d*)(\s*)\)/i', // 防止 SQL 盲注
+            '/benchmark\((.*)\,(.*)\)/i', // 防止 SQL 盲注
+            '/base64_decode\(/i', // 防止 SQL 变种注入
+            '/(?:from\W+information_schema\W)/i', // 注意这里的 (?:...) 是不合法的,应该是 (?:...) 表示非捕获组,但通常我们不需要这个
+            '/(?:current_|user|database|schema|connection_id)\s*\(/i', // 防止 SQL 注入(注意去掉了不必要的 (?:...))
+            '/(?:etc\/\W*passwd)/i', // 防止窥探 Linux 用户信息
+            '/into(\s+)(?:dump|out)file\s*/i', // 禁用 MySQL 导出函数
+            '/group\s+by.+\(/i', // 防止 SQL 注入
+            '/(?:define|eval|file_get_contents|include|require|require_once|shell_exec|phpinfo|system|passthru|preg_\w+|execute|echo|print|print_r|var_dump|(fp)open|alert|showmodaldialog)\(/i', // 禁用 webshell 相关某些函数
+            '/(gopher|doc|php|glob|file|phar|zlib|ftp|ldap|dict|ogg|data)\:\/\//i', // 防止一些协议攻击(注意协议后的三个斜杠)
+            '/\$_(GET|POST|COOKIE|FILES|SESSION|ENV|GLOBALS|SERVER)\[/i', // 禁用一些内置变量,注意 PHP 变量名通常是大写的
+            '/<(iframe|script|body|img|layer|div|meta|style|base|object|input)/i', // 防止 XSS 标签植入
+            '/(onmouseover|onerror|onload|onclick)\=/i', // 防止 XSS 事件植入
+            '/\|\|.*?(?:ls|pwd|whoami|ll|ifconfig|ipconfig|&&|chmod|cd|mkdir|rmdir|cp|mv)/i', // 防止执行 shell(注意去掉了不合适的 ifconfog)
+            '/\sand\s+.*=.*/i' // 匹配 and 1=1
+        ];
+        if (filter_var($str, FILTER_VALIDATE_URL)) {
+            $url = parse_url($str);
+            if (!isset($url['scheme'])) return $str;
+            $host = $url['scheme'] . '://' . $url['host'];
+            $str = $host . preg_replace($rules, '', str_replace($host, '', $str));
+        } else {
+            $str = preg_replace($rules, '', $str);
+        }
+        return $str;
+    }
+}
+
 if (!function_exists('is_brokerage_statu')) {
 
     /**
@@ -1108,7 +1151,7 @@ if (!function_exists('out_push')) {
 
 if (!function_exists('dump_sql')) {
     /**
-     * 默认数据推送
+     * 打印sql
      * @param string $pushUrl
      * @param array $data
      * @param string $tip

+ 1 - 1
crmeb/app/dao/activity/bargain/StoreBargainDao.php

@@ -119,7 +119,7 @@ class StoreBargainDao extends BaseDao
             ->where('start_time', '<=', time())
             ->where('stop_time', '>=', time())
             ->where('product_id', 'IN', function ($query) {
-                $query->name('store_product')->where('is_show', 1)->where('is_del', 0)->field('id');
+                $query->name('store_product')->where('is_del', 0)->field('id');
             })->with('product')->field($field)->page($page, $limit)->order('sort DESC,id DESC')->select()->toArray();
     }
 

+ 1 - 1
crmeb/app/dao/activity/combination/StoreCombinationDao.php

@@ -47,7 +47,7 @@ class StoreCombinationDao extends BaseDao
             $query->where('start_time', '<=', $startTime)->where('stop_time', '>=', $stopTime);
         })->when(isset($where['storeProductId']), function ($query) {
             $query->where('product_id', 'IN', function ($query) {
-                $query->name('store_product')->where('is_show', 1)->where('is_del', 0)->field('id');
+                $query->name('store_product')->where('is_del', 0)->field('id');
             });
         })->when(isset($where['sid']) && $where['sid'], function ($query) use ($where) {
             $query->whereIn('product_id', function ($query) use ($where) {

+ 2 - 1
crmeb/app/dao/activity/combination/StorePinkDao.php

@@ -133,6 +133,7 @@ class StorePinkDao extends BaseDao
     {
         return $this->search(['status' => 2, 'is_refund' => 0])
 //            ->where('uid', '<>', $uid)
+                ->limit(10)
             ->select()->toArray();
     }
 
@@ -197,6 +198,6 @@ class StorePinkDao extends BaseDao
             ->where('status', 1)
             ->where('k_id', 0)
             ->where('is_refund', 0)
-            ->field('id,people,k_id,uid,stop_time')->select()->toArray();
+            ->field('id,people,k_id,uid,stop_time,order_id_key')->select()->toArray();
     }
 }

+ 1 - 1
crmeb/app/dao/activity/seckill/StoreSeckillDao.php

@@ -184,7 +184,7 @@ class StoreSeckillDao extends BaseDao
             ->where('stop_time', '>=', time() - 86400)
             ->where('time_id', $time)
             ->where('product_id', 'IN', function ($query) {
-                $query->name('store_product')->where('is_show', 1)->where('is_del', 0)->field('id');
+                $query->name('store_product')->where('is_del', 0)->field('id');
             })->when($page != 0, function ($query) use ($page, $limit) {
                 $query->page($page, $limit);
             })->order('sort desc,id desc')->select()->toArray();

+ 16 - 24
crmeb/app/dao/article/ArticleDao.php

@@ -53,6 +53,10 @@ class ArticleDao extends BaseDao
      * @param int $page
      * @param int $limit
      * @return mixed
+     * @throws \ReflectionException
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
      */
     public function getList(array $where, int $page, int $limit)
     {
@@ -63,6 +67,10 @@ class ArticleDao extends BaseDao
      * 获取一条数据
      * @param $id
      * @return mixed
+     * @throws \ReflectionException
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
      */
     public function read($id)
     {
@@ -73,41 +81,25 @@ class ArticleDao extends BaseDao
     }
 
     /**
-     * @param array $where
-     * @param int $page
-     * @param int $limit
-     * @param string $field
-     * @return array
+     * 新闻分类下的文章
+     * @param $new_id
+     * @return mixed
      * @throws \think\db\exception\DataNotFoundException
      * @throws \think\db\exception\DbException
      * @throws \think\db\exception\ModelNotFoundException
      */
-    public function cidByArticleList(array $where, int $page, int $limit, string $field = '*')
-    {
-        return $this->search(['status' => 1, 'hide' => 0])
-            ->when(isset($where['cid']) && $where['cid'], function ($query) use ($where) {
-                $query->where('cid', $where['cid']);
-            })->when(isset($where['is_hot']) && $where['is_hot'], function ($query) use ($where) {
-                $query->where('is_hot', $where['is_hot']);
-            })->when(isset($where['is_banner']) && $where['is_banner'], function ($query) use ($where) {
-                $query->where('is_banner', $where['is_banner']);
-            })->when($page != 0, function ($query) use ($page, $limit) {
-                $query->page($page, $limit);
-            })->order('add_time desc')->field($field)->select()->toArray();
-    }
-
-    /**新闻分类下的文章
-     * @param $new_id
-     * @return mixed
-     */
     public function articleLists($new_id)
     {
         return $this->getModel()->where('hide', 0)->where('id', 'in', $new_id)->select();
     }
 
-    /**图文详情
+    /**
+     * 图文详情
      * @param $new_id
      * @return mixed
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
      */
     public function articleContentList($new_id)
     {

+ 1 - 1
crmeb/app/dao/order/OtherOrderDao.php

@@ -54,7 +54,7 @@ class OtherOrderDao extends BaseDao
      */
     public function getTrendData($time, $type, $timeType)
     {
-        return $this->getModel()->when($type != '', function ($query) use ($type) {
+        return $this->getModel()->where('member_type', '<>', 0)->when($type != '', function ($query) use ($type) {
             $query->where('channel_type', $type);
         })->where(function ($query) use ($time) {
             if ($time[0] == $time[1]) {

+ 2 - 2
crmeb/app/dao/order/StoreOrderDao.php

@@ -915,7 +915,7 @@ class StoreOrderDao extends BaseDao
      */
     public function seckillPeople($id, $keyword, $page = 0, $limit = 0)
     {
-        return $this->getModel()->where('paid', 1)->whereIn('refund_type', [0, 3])->where('is_del', 0)
+        return $this->getModel()->where('paid', 1)->where('pid', '<>', -1)->whereIn('refund_type', [0, 3])->where('is_del', 0)
             ->when($id != 0, function ($query) use ($id) {
                 $query->where('seckill_id', $id);
             })->when($keyword != '', function ($query) use ($keyword) {
@@ -1014,7 +1014,7 @@ class StoreOrderDao extends BaseDao
      */
     public function combinationStatisticsOrder($id, $where, $page = 0, $limit = 0)
     {
-        return $this->search($where)->where('combination_id', $id)
+        return $this->search($where)->where('combination_id', $id)->where('pid', '<>', -1)
             ->when($page && $limit, function ($query) use ($page, $limit) {
                 $query->page($page, $limit);
             })->field(['uid', 'order_id', 'real_name', 'status', 'pay_price', 'total_num', 'add_time', 'pay_time', 'paid'])->order('add_time desc')->select()->toArray();

+ 2 - 2
crmeb/app/dao/product/product/StoreProductReplyDao.php

@@ -54,7 +54,7 @@ class StoreProductReplyDao extends BaseDao
      */
     public function getProductReply(int $productId)
     {
-        return $this->search(['product_id' => $productId, 'is_del' => 0])
+        return $this->search(['product_id' => $productId, 'is_del' => 0, 'status' => 1])
             ->with(['cartInfo', 'userInfo'])
             ->order('add_time DESC,product_score DESC,service_score DESC,add_time DESC')
             ->find();
@@ -68,7 +68,7 @@ class StoreProductReplyDao extends BaseDao
      */
     public function replyWhere(int $id, int $type = 0)
     {
-        return $this->search(['product_id' => $id, 'is_del' => 0])
+        return $this->search(['product_id' => $id, 'is_del' => 0, 'status' => 1])
             ->when($type == 1, function ($query) {
                 $query->where('product_score', 5)->where('service_score', 5);
             })->when($type == 2, function ($query) {

+ 2 - 1
crmeb/app/dao/product/product/StoreProductReplyStoreProductDao.php

@@ -8,7 +8,7 @@
 // +----------------------------------------------------------------------
 // | Author: CRMEB Team <admin@crmeb.com>
 // +----------------------------------------------------------------------
-declare (strict_types = 1);
+declare (strict_types=1);
 
 namespace app\dao\product\product;
 
@@ -106,6 +106,7 @@ class StoreProductReplyStoreProductDao extends BaseDao
         if ($where['product_id']) $model = $model->where('r.product_id', $where['product_id']);
         if ($where['store_name']) $model = $model->where('p.store_name|r.product_id', 'Like', '%' . $where['store_name'] . '%');
         if ($where['account']) $model = $model->where('r.nickname', 'LIKE', '%' . $where['account'] . '%');
+        if ($where['status'] !== '') $model = $model->where('status', $where['status']);
         if ($where['key'] != '') {
             $model = $model->order($where['key'], $where['order']);
         } else {

+ 25 - 0
crmeb/app/dao/system/SystemCrudListDao.php

@@ -0,0 +1,25 @@
+<?php
+
+namespace app\dao\system;
+
+use app\dao\BaseDao;
+use app\model\system\SystemCrudList;
+
+/**
+ * @author wuhaotian
+ * @email 442384644@qq.com
+ * @date 2024/5/20
+ */
+class SystemCrudListDao extends BaseDao
+{
+    /**
+     * @return string
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/5/20
+     */
+    protected function setModel(): string
+    {
+        return SystemCrudList::class;
+    }
+}

+ 18 - 0
crmeb/app/dao/system/SystemEventDao.php

@@ -0,0 +1,18 @@
+<?php
+
+namespace app\dao\system;
+
+use app\dao\BaseDao;
+use app\model\system\SystemEvent;
+
+class SystemEventDao extends BaseDao
+{
+    /**
+     * 设置模型
+     * @return string
+     */
+    protected function setModel(): string
+    {
+        return SystemEvent::class;
+    }
+}

+ 18 - 0
crmeb/app/dao/system/SystemEventDataDao.php

@@ -0,0 +1,18 @@
+<?php
+
+namespace app\dao\system;
+
+use app\dao\BaseDao;
+use app\model\system\SystemEventData;
+
+class SystemEventDataDao extends BaseDao
+{
+    /**
+     * 设置模型
+     * @return string
+     */
+    protected function setModel(): string
+    {
+        return SystemEventData::class;
+    }
+}

+ 2 - 2
crmeb/app/event.php

@@ -45,8 +45,8 @@ return [
         'NoticeListener' => [\app\listener\notice\NoticeListener::class], //通知->消息事件
         'CustomNoticeListener' => [\app\listener\notice\CustomNoticeListener::class], //通知->自定义消息发送事件
         'NotifyListener' => [\app\listener\pay\NotifyListener::class],//支付异步回调
-        'CrontabListener' => [\app\listener\crontab\SystemCrontabListener::class],//定时任务事件
-        'OrderShipping' => [\app\listener\order\OrderShippingListener::class],//定时任务事件
+        'OrderShippingListener' => [\app\listener\order\OrderShippingListener::class],//小程序发货管理
+        'CustomEventListener' => [\app\listener\CustomEventListener::class],//自定义事件
     ],
 ];
 

+ 56 - 0
crmeb/app/jobs/OrderInvoiceJob.php

@@ -0,0 +1,56 @@
+<?php
+
+namespace app\jobs;
+
+use app\services\order\StoreOrderInvoiceServices;
+use crmeb\basic\BaseJobs;
+use crmeb\traits\QueueTrait;
+
+class OrderInvoiceJob extends BaseJobs
+{
+    use QueueTrait;
+
+    /**
+     * 自动开票队列
+     * @param $id
+     * @return bool
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/5/16
+     */
+    public function autoInvoice($id)
+    {
+        try {
+            if (sys_config('elec_invoice', 1) != 1) {
+                return true;
+            }
+            /** @var StoreOrderInvoiceServices $services */
+            $services = app()->make(StoreOrderInvoiceServices::class);
+            $services->invoiceIssuance($id);
+        } catch (\Exception $e) {
+        }
+        return true;
+    }
+
+    /**
+     * 自动冲红队列
+     * @param $id
+     * @return bool
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/5/16
+     */
+    public function autoInvoiceRed($id)
+    {
+        try {
+            if (sys_config('elec_invoice', 1) != 1) {
+                return true;
+            }
+            /** @var StoreOrderInvoiceServices $services */
+            $services = app()->make(StoreOrderInvoiceServices::class);
+            $services->redInvoiceIssuance($id);
+        } catch (\Exception $e) {
+        }
+        return true;
+    }
+}

+ 26 - 0
crmeb/app/listener/CustomEventListener.php

@@ -0,0 +1,26 @@
+<?php
+
+namespace app\listener;
+
+use app\services\system\SystemEventServices;
+use think\facade\Log;
+
+class CustomEventListener
+{
+    public function handle($event)
+    {
+        [$mark, $data] = $event;
+        try {
+            $list = app()->make(SystemEventServices::class)->selectList(['mark' => $mark, 'is_del' => 0, 'is_open' => 1])->toArray();
+            foreach ($list as $item) {
+                eval(json_decode($item['customCode']));
+            }
+        } catch (\Throwable $e) {
+            $listener_log_open = config("log.listener_log", false);
+            if ($listener_log_open) {
+                $date = date('Y-m-d H:i:s', time());
+                Log::write($date . '自定义事件错误:' . $e->getMessage(), 'listener');
+            }
+        }
+    }
+}

+ 0 - 79
crmeb/app/listener/crontab/SystemCrontabListener.php

@@ -1,79 +0,0 @@
-<?php
-
-namespace app\listener\crontab;
-
-use app\services\system\crontab\CrontabRunServices;
-use app\services\system\crontab\SystemCrontabServices;
-use crmeb\interfaces\ListenerInterface;
-use think\helper\Str;
-use Workerman\Crontab\Crontab;
-
-/**
- * 系统定时任务
- */
-class SystemCrontabListener implements ListenerInterface
-{
-    public function handle($event): void
-    {
-        $systemCrontabServices = app()->make(SystemCrontabServices::class);
-        $crontabRunServices = app()->make(CrontabRunServices::class);
-
-        //自动写入文件方便检测是否启动定时任务命令
-        new Crontab('*/6 * * * * *', function () {
-            file_put_contents(root_path() . 'runtime/.timer', time());
-        });
-
-        $list = $systemCrontabServices->selectList(['is_del' => 0, 'is_open' => 1])->toArray();
-        foreach ($list as &$item) {
-            //转化小驼峰
-            $functionName = Str::camel($item['mark']);
-            //获取定时任务时间字符串
-            $timeStr = $this->getTimerStr($item);
-            new Crontab($timeStr, function () use ($crontabRunServices, $functionName) {
-                $crontabRunServices->$functionName();
-            });
-        }
-    }
-
-    /**
-     * 获取定时任务时间表达式
-     * 0   1   2   3   4   5
-     * |   |   |   |   |   |
-     * |   |   |   |   |   +------ day of week (0 - 6) (Sunday=0)
-     * |   |   |   |   +------ month (1 - 12)
-     * |   |   |   +-------- day of month (1 - 31)
-     * |   |   +---------- hour (0 - 23)
-     * |   +------------ min (0 - 59)
-     * +-------------- sec (0-59)[可省略,如果没有0位,则最小时间粒度是分钟]
-     * @param $data
-     * @return string
-     */
-    public function getTimerStr($data): string
-    {
-        $timeStr = '';
-        switch ($data['type']) {
-            case 1:// 每隔几秒
-                $timeStr = '*/' . $data['second'] . ' * * * * *';
-                break;
-            case 2:// 每隔几分
-                $timeStr = '0 */' . $data['minute'] . ' * * * *';
-                break;
-            case 3:// 每隔几时第几分钟执行
-                $timeStr = '0 ' . $data['minute'] . ' */' . $data['hour'] . ' * * *';
-                break;
-            case 4:// 每隔几日第几小时第几分钟执行
-                $timeStr = '0 ' . $data['minute'] . ' ' . $data['hour'] . ' */' . $data['day'] . ' * *';
-                break;
-            case 5:// 每日几时几分几秒
-                $timeStr = $data['second'] . ' ' . $data['minute'] . ' ' . $data['hour'] . ' * * *';
-                break;
-            case 6:// 每周周几几时几分几秒
-                $timeStr = $data['second'] . ' ' . $data['minute'] . ' ' . $data['hour'] . ' * * ' . ($data['week'] == 7 ? 0 : $data['week']);
-                break;
-            case 7:// 每月几日几时几分几秒
-                $timeStr = $data['second'] . ' ' . $data['minute'] . ' ' . $data['hour'] . ' ' . $data['day'] . ' * *';
-                break;
-        }
-        return $timeStr;
-    }
-}

+ 9 - 1
crmeb/app/listener/order/OrderPaySuccessListener.php

@@ -5,6 +5,7 @@ namespace app\listener\order;
 
 
 use app\jobs\AgentJob;
+use app\jobs\OrderInvoiceJob;
 use app\jobs\OrderJob;
 use app\jobs\ProductLogJob;
 use app\services\activity\seckill\StoreSeckillServices;
@@ -55,7 +56,14 @@ class OrderPaySuccessListener implements ListenerInterface
 
         //修改开票数据支付状态
         $orderInvoiceServices = app()->make(StoreOrderInvoiceServices::class);
-        $orderInvoiceServices->update(['order_id' => $orderInfo['id']], ['is_pay' => 1]);
+        $invoiceInfo = $orderInvoiceServices->get(['order_id' => $orderInfo['id']]);
+        if ($invoiceInfo) {
+            $invoiceInfo->is_pay = 1;
+            if ($invoiceInfo->save() && sys_config('elec_invoice', 1) == 1 && sys_config('auto_invoice', 1) == 1) {
+                //自动开票
+                OrderInvoiceJob::dispatchSecs(10, 'autoInvoice', [$invoiceInfo['id']]);
+            }
+        }
 
         //虚拟商品自动发货
         if ($orderInfo['virtual_type'] > 0 && $orderInfo['combination_id'] == 0) {

+ 1 - 1
crmeb/app/model/activity/combination/StoreCombination.php

@@ -61,7 +61,7 @@ class StoreCombination extends BaseModel
      */
     public function total()
     {
-        return $this->hasOne(StoreProduct::class, 'id', 'product_id')->where('is_show', 1)->where('is_del', 0)->field(['SUM(sales+ficti) as total', 'id', 'price'])->bind([
+        return $this->hasOne(StoreProduct::class, 'id', 'product_id')->where('is_show', 1)->where('is_del', 0)->field(['(sales+ficti) as total', 'id', 'price'])->bind([
             'total' => 'total', 'product_price' => 'price'
         ]);
     }

+ 10 - 4
crmeb/app/model/article/Article.php

@@ -61,7 +61,7 @@ class Article extends BaseModel
      */
     public function cateName()
     {
-        return $this->hasOne(ArticleCategory::class, 'id', 'cid')->bind(['catename'=>'title']);
+        return $this->hasOne(ArticleCategory::class, 'id', 'cid')->bind(['catename' => 'title']);
     }
 
     /**
@@ -95,7 +95,9 @@ class Article extends BaseModel
      */
     public function searchTitleAttr($query, $value, $data)
     {
-        $query->where('title', 'like', '%' . $value . '%');
+        if ($value !== '') {
+            $query->where('title', 'like', '%' . $value . '%');
+        }
     }
 
     /**
@@ -106,7 +108,9 @@ class Article extends BaseModel
      */
     public function searchIsHotAttr($query, $value, $data)
     {
-        $query->where('is_hot', $value);
+        if ($value !== '') {
+            $query->where('is_hot', $value);
+        }
     }
 
     /**
@@ -117,7 +121,9 @@ class Article extends BaseModel
      */
     public function searchIsBannerAttr($query, $value, $data)
     {
-        $query->where('is_banner', $value);
+        if ($value !== '') {
+            $query->where('is_banner', $value);
+        }
     }
 
 }

+ 19 - 11
crmeb/app/model/order/OtherOrder.php

@@ -20,6 +20,7 @@ use think\Model;
 class OtherOrder extends BaseModel
 {
     use ModelTrait;
+
     /**
      * 数据表主键
      * @var string
@@ -34,7 +35,7 @@ class OtherOrder extends BaseModel
 
     protected $insert = ['add_time'];
 
-   // protected $hidden = ['add_time', 'is_del', 'uid'];
+    // protected $hidden = ['add_time', 'is_del', 'uid'];
 
     /**订单类型
      * @param $query
@@ -44,15 +45,17 @@ class OtherOrder extends BaseModel
     {
         if (is_array($value)) {
             $query->where('type', 'in', $value);
-        }else{
+        } else {
             $query->where('type', $value);
         }
 
     }
+
     public function searchPaidAttr($query, $value)
     {
         $query->where('paid', $value);
     }
+
     /**支付方式不属于
      * @param $query
      * @param $value
@@ -61,6 +64,7 @@ class OtherOrder extends BaseModel
     {
         $query->where('pay_type', '<>', $value);
     }
+
     /**
      * 用户来源
      * @param Model $query
@@ -77,7 +81,7 @@ class OtherOrder extends BaseModel
      */
     public function searchOrderIdAttr($query, $value)
     {
-        if ($value != ""){
+        if ($value != "") {
             $query->where('order_id', $value);
         }
 
@@ -99,7 +103,11 @@ class OtherOrder extends BaseModel
     public function searchMemberTypeAttr($query, $value)
     {
         if ($value && $value != 'card' && $value != 'free') {
-            $query->where('member_type', $value);
+            if ($value == -1) {
+                $query->where('member_type', '<>', 0);
+            } else {
+                $query->where('member_type', $value);
+            }
         } elseif ($value == 'card') {
             $query->where('member_type', 'free')->where('code', '<>', '');
         } elseif ($value == 'free') {
@@ -114,14 +122,14 @@ class OtherOrder extends BaseModel
      */
     public function searchPayTypeAttr($query, $value)
     {
-        if ($value){
-            if ($value == "free"){
-                $query->where(function($query){
-                    $query->where('type', 'in', [0,2])->whereOr(function($query){
+        if ($value) {
+            if ($value == "free") {
+                $query->where(function ($query) {
+                    $query->where('type', 'in', [0, 2])->whereOr(function ($query) {
                         $query->where(['type' => 1, 'is_free' => 1]);
                     });
                 });
-            }else{
+            } else {
                 $query->where('pay_type', $value);
             }
 
@@ -134,7 +142,7 @@ class OtherOrder extends BaseModel
      */
     public function searchAddTimeAttr($query, $value)
     {
-        if ($value){
+        if ($value) {
             $query->whereTime('add_time', 'between', $value);
         }
     }
@@ -145,7 +153,7 @@ class OtherOrder extends BaseModel
      */
     public function searchUidAttr($query, $value)
     {
-        if ($value){
+        if ($value) {
             $query->where('uid', 'in', $value);
         }
     }

+ 148 - 141
crmeb/app/model/order/StoreOrderInvoice.php

@@ -1,141 +1,148 @@
-<?php
-// +----------------------------------------------------------------------
-// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
-// +----------------------------------------------------------------------
-// | Copyright (c) 2016~2023 https://www.crmeb.com All rights reserved.
-// +----------------------------------------------------------------------
-// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
-// +----------------------------------------------------------------------
-// | Author: CRMEB Team <admin@crmeb.com>
-// +----------------------------------------------------------------------
-
-namespace app\model\order;
-
-
-use app\model\user\UserInvoice;
-use crmeb\basic\BaseModel;
-use crmeb\traits\ModelTrait;
-use think\Model;
-
-/**
- * Class StoreOrderInvoice
- * @package app\model\order
- */
-class StoreOrderInvoice extends BaseModel
-{
-    use ModelTrait;
-
-    protected $pk = 'id';
-
-    protected $name = 'store_order_invoice';
-
-    protected $autoWriteTimestamp = 'int';
-
-    protected $createTime = 'add_time';
-
-    protected function setAddTimeAttr()
-    {
-        return time();
-    }
-
-    /**
-     * 添加时间获取器
-     * @param $value
-     * @return false|string
-     */
-    public function getAddTimeAttr($value)
-    {
-        if (!empty($value)) {
-            return is_string($value) ? $value : date('Y-m-d H:i:s', (int)$value);
-        }
-        return '';
-    }
-
-    public function getInfoAttr($value)
-    {
-        if (!empty($value)) {
-            return json_decode($value, true);
-        }
-        return [];
-    }
-
-    public function order()
-    {
-        return $this->hasOne(StoreOrder::class, 'id', 'order_id');
-    }
-
-    public function invoiceInfo()
-    {
-        return $this->hasOne(UserInvoice::class, 'id', 'invoice_id');
-    }
-
-    public function searchCategoryAttr($query, $value)
-    {
-        if ($value !== '') {
-            $query->where('category', $value);
-        }
-    }
-
-    /**
-     * @param Model $query
-     * @param $value
-     */
-    public function searchUidAttr($query, $value)
-    {
-        if ($value !== '' && !is_null($value)) $query->where('uid', $value);
-    }
-
-    /**
-     * @param Model $query
-     * @param $value
-     */
-    public function searchOrderIdAttr($query, $value)
-    {
-        if ($value !== '' && !is_null($value)) $query->where('order_id', $value);
-    }
-
-    /**
-     * @param Model $query
-     * @param $value
-     */
-    public function searchInvoiceIdAttr($query, $value)
-    {
-        if ($value !== '' && !is_null($value)) $query->where('invoice_id', $value);
-    }
-
-    /**
-     * @param Model $query
-     * @param $value
-     */
-    public function searchHeaderTypeAttr($query, $value)
-    {
-        if ($value !== '' && !is_null($value)) $query->where('header_type', $value);
-    }
-
-    /**
-     * @param Model $query
-     * @param $value
-     */
-    public function searchTypeAttr($query, $value)
-    {
-        if ($value !== '' && !is_null($value)) $query->where('type', $value);
-    }
-
-    public function searchInvoiceTimeAttr($query, $value)
-    {
-        if ($value !== '') {
-            if (is_array($value)) {
-                $query->whereTime('invoice_time', 'between', $value);
-            } else {
-                $query->where('invoice_time', $value);
-            }
-        }
-    }
-
-    public function searchIsPayAttr($query, $value)
-    {
-        if ($value !== '') {
-            $query->where('is_pay', $value);
-        }
-    }
-}
+<?php
+// +----------------------------------------------------------------------
+// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2016~2023 https://www.crmeb.com All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
+// +----------------------------------------------------------------------
+// | Author: CRMEB Team <admin@crmeb.com>
+// +----------------------------------------------------------------------
+
+namespace app\model\order;
+
+
+use app\model\user\UserInvoice;
+use crmeb\basic\BaseModel;
+use crmeb\traits\ModelTrait;
+use think\Model;
+
+/**
+ * Class StoreOrderInvoice
+ * @package app\model\order
+ */
+class StoreOrderInvoice extends BaseModel
+{
+    use ModelTrait;
+
+    protected $pk = 'id';
+
+    protected $name = 'store_order_invoice';
+
+    protected $autoWriteTimestamp = 'int';
+
+    protected $createTime = 'add_time';
+
+    protected function setAddTimeAttr()
+    {
+        return time();
+    }
+
+    /**
+     * 添加时间获取器
+     * @param $value
+     * @return false|string
+     */
+    public function getAddTimeAttr($value)
+    {
+        if (!empty($value)) {
+            return is_string($value) ? $value : date('Y-m-d H:i:s', (int)$value);
+        }
+        return '';
+    }
+
+    public function getInfoAttr($value)
+    {
+        if (!empty($value)) {
+            return json_decode($value, true);
+        }
+        return [];
+    }
+
+    public function order()
+    {
+        return $this->hasOne(StoreOrder::class, 'id', 'order_id');
+    }
+
+    public function invoiceInfo()
+    {
+        return $this->hasOne(UserInvoice::class, 'id', 'invoice_id');
+    }
+
+    public function searchCategoryAttr($query, $value)
+    {
+        if ($value !== '') {
+            $query->where('category', $value);
+        }
+    }
+
+    /**
+     * @param Model $query
+     * @param $value
+     */
+    public function searchUidAttr($query, $value)
+    {
+        if ($value !== '' && !is_null($value)) $query->where('uid', $value);
+    }
+
+    /**
+     * @param Model $query
+     * @param $value
+     */
+    public function searchOrderIdAttr($query, $value)
+    {
+        if ($value !== '' && !is_null($value)) $query->where('order_id', $value);
+    }
+
+    /**
+     * @param Model $query
+     * @param $value
+     */
+    public function searchInvoiceIdAttr($query, $value)
+    {
+        if ($value !== '' && !is_null($value)) $query->where('invoice_id', $value);
+    }
+
+    /**
+     * @param Model $query
+     * @param $value
+     */
+    public function searchHeaderTypeAttr($query, $value)
+    {
+        if ($value !== '' && !is_null($value)) $query->where('header_type', $value);
+    }
+
+    /**
+     * @param Model $query
+     * @param $value
+     */
+    public function searchTypeAttr($query, $value)
+    {
+        if ($value !== '' && !is_null($value)) $query->where('type', $value);
+    }
+
+    public function searchInvoiceTimeAttr($query, $value)
+    {
+        if ($value !== '') {
+            if (is_array($value)) {
+                $query->whereTime('invoice_time', 'between', $value);
+            } else {
+                $query->where('invoice_time', $value);
+            }
+        }
+    }
+
+    public function searchIsPayAttr($query, $value)
+    {
+        if ($value !== '') {
+            $query->where('is_pay', $value);
+        }
+    }
+
+    public function searchIsDelAttr($query, $value)
+    {
+        if ($value !== '') {
+            $query->where('is_del', $value);
+        }
+    }
+}

+ 1 - 1
crmeb/app/model/product/product/StoreProduct.php

@@ -101,7 +101,7 @@ class StoreProduct extends BaseModel
      */
     public function searchIsShowAttr($query, $value)
     {
-        $query->where('is_show', $value ?? 1);
+        if ($value != -1) $query->where('is_show', $value ?? 1);
     }
 
     /**

+ 10 - 0
crmeb/app/model/product/product/StoreProductReply.php

@@ -161,4 +161,14 @@ class StoreProductReply extends BaseModel
     {
         $query->where('product_score', $value);
     }
+
+    /**
+     * 状态搜索器
+     * @param Model $query
+     * @param $value
+     */
+    public function searchStatusAttr($query, $value)
+    {
+        if ($value !== '') $query->where('status', $value);
+    }
 }

+ 18 - 4
crmeb/app/model/system/SystemCrudData.php

@@ -35,10 +35,10 @@ class SystemCrudData extends BaseModel
      */
     protected $pk = 'id';
 
-    public function getValueAttr($value)
-    {
-        return json_decode($value, true);
-    }
+//    public function getValueAttr($value)
+//    {
+//        return json_decode($value, true);
+//    }
 
     /**
      * @param $query
@@ -53,4 +53,18 @@ class SystemCrudData extends BaseModel
             $query->where('name', 'like', '%' . $value . '%');
         }
     }
+
+    /**
+     * @param $query
+     * @param $value
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/5/20
+     */
+    public function searchPidAttr($query, $value)
+    {
+        if ($value !== '') {
+            $query->where('pid', $value);
+        }
+    }
 }

+ 30 - 0
crmeb/app/model/system/SystemCrudList.php

@@ -0,0 +1,30 @@
+<?php
+
+namespace app\model\system;
+
+use crmeb\basic\BaseModel;
+
+/**
+ * @author wuhaotian
+ * @email 442384644@qq.com
+ * @date 2024/5/20
+ */
+class SystemCrudList extends BaseModel
+{
+    /**
+     * @var string
+     */
+    protected $name = 'system_crud_list';
+
+    /**
+     * @var string
+     */
+    protected $pk = 'id';
+
+    public function searchStatusAttr($query, $value)
+    {
+        if ($value !== '') {
+            $query->where('status', $value);
+        }
+    }
+}

+ 23 - 0
crmeb/app/model/system/SystemEvent.php

@@ -0,0 +1,23 @@
+<?php
+
+namespace app\model\system;
+
+use crmeb\basic\BaseModel;
+use crmeb\traits\ModelTrait;
+
+class SystemEvent extends BaseModel
+{
+    use ModelTrait;
+
+    /**
+     * 数据表主键
+     * @var string
+     */
+    protected $pk = 'id';
+
+    /**
+     * 模型名称
+     * @var string
+     */
+    protected $name = 'system_event';
+}

+ 23 - 0
crmeb/app/model/system/SystemEventData.php

@@ -0,0 +1,23 @@
+<?php
+
+namespace app\model\system;
+
+use crmeb\basic\BaseModel;
+use crmeb\traits\ModelTrait;
+
+class SystemEventData extends BaseModel
+{
+    use ModelTrait;
+
+    /**
+     * 数据表主键
+     * @var string
+     */
+    protected $pk = 'id';
+
+    /**
+     * 模型名称
+     * @var string
+     */
+    protected $name = 'system_event_data';
+}

+ 15 - 1
crmeb/app/model/system/config/SystemConfig.php

@@ -57,7 +57,9 @@ class SystemConfig extends BaseModel
      */
     public function searchTabIdAttr($query, $value)
     {
-        $query->where('config_tab_id', $value);
+        if ($value != 0) {
+            $query->where('config_tab_id', $value);
+        }
     }
 
     /**
@@ -79,4 +81,16 @@ class SystemConfig extends BaseModel
     {
         $query->where('value', $value);
     }
+
+    /**
+     * info搜索器
+     * @param Model $query
+     * @param $value
+     */
+    public function searchConfigNameAttr($query, $value)
+    {
+        if ($value !== '') {
+            $query->where('info|menu_name', 'like', "%$value%");
+        }
+    }
 }

+ 20 - 0
crmeb/app/model/system/crontab/SystemCrontab.php

@@ -20,4 +20,24 @@ class SystemCrontab extends BaseModel
      * @var string
      */
     protected $name = 'system_timer';
+
+    /**
+     * 是否自定义定时任务搜索器
+     * @param $query
+     * @param $value
+     * @param $data
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/6/6
+     */
+    public function searchCustomAttr($query, $value, $data)
+    {
+        if ($value !== '') {
+            if ($value == 0) {
+                $query->where('mark', '<>', 'customTimer');
+            } else {
+                $query->where('mark', 'customTimer');
+            }
+        }
+    }
 }

+ 36 - 0
crmeb/app/outapi/controller/User.php

@@ -185,4 +185,40 @@ class User extends AuthController
         }
         return app('json')->success(100010);
     }
+
+    /**
+     * 修改余额
+     * @param $uid
+     * @return \think\Response
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/5/20
+     */
+    public function changeBalance($uid)
+    {
+        [$money] = $this->request->postMore([
+            ['money', 0],
+        ], true);
+        if (!$uid) return app('json')->fail(100100);
+        $this->services->changeUserData((int)$uid, $money, 'now_money');
+        return app('json')->success('修改成功');
+    }
+
+    /**
+     * 修改积分
+     * @param $uid
+     * @return \think\Response
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/5/20
+     */
+    public function changePoint($uid)
+    {
+        [$integral] = $this->request->postMore([
+            ['integral', 0],
+        ], true);
+        if (!$uid) return app('json')->fail(100100);
+        $this->services->changeUserData((int)$uid, $integral, 'integral');
+        return app('json')->success('修改成功');
+    }
 }

+ 2 - 0
crmeb/app/outapi/route/route.php

@@ -88,6 +88,8 @@ Route::group(function () {
             Route::put('user/:uid', 'User/update')->option(['real_name' => '修改用户']);
             Route::put('user/give_balance/:uid', 'User/giveBalance')->option(['real_name' => '赠送余额']);
             Route::put('user/give_point/:uid', 'User/givePoint')->option(['real_name' => '赠送积分']);
+            Route::put('user/change_balance/:uid', 'User/changeBalance')->option(['real_name' => '修改余额']);
+            Route::put('user/change_point/:uid', 'User/changePoint')->option(['real_name' => '修改积分']);
         })->option(['mark' => 'user', 'mark_name' => '用户']);
 
     })->middleware(AuthTokenMiddleware::class);

+ 12 - 1
crmeb/app/services/BaseServices.php

@@ -98,8 +98,19 @@ abstract class BaseServices
             throw new ApiException(410027);
         }
         if ($type == 'api') {
+            $user = app()->make(UserServices::class)->get($id);
             //自定义消息-用户登录成功
-            event('CustomNoticeListener', [$id, app()->make(UserServices::class)->get($id), 'login_success']);
+            event('CustomNoticeListener', [$id, $user, 'login_success']);
+
+            //自定义事件-用户登录
+            event('CustomEventListener', ['user_login', [
+                'uid' => $user->uid,
+                'nickname' => $user->nickname,
+                'phone' => $user->phone,
+                'add_time' => date('Y-m-d H:i:s', $user->add_time),
+                'login_time' => date('Y-m-d H:i:s'),
+                'user_type' => $user->user_type,
+            ]]);
         }
         return $jwtAuth->createToken($id, $type, ['pwd' => md5($pwd)]);
     }

+ 5 - 4
crmeb/app/services/activity/bargain/StoreBargainServices.php

@@ -130,7 +130,7 @@ class StoreBargainServices extends BaseServices
         $items = $data['items'];
         $data['start_time'] = strtotime($data['section_time'][0]);
         $data['stop_time'] = strtotime($data['section_time'][1]);
-        $data['image'] = $data['images'][0];
+        $data['image'] = $data['image'];
         $data['images'] = json_encode($data['images']);
         $data['stock'] = $detail[0]['stock'];
         $data['quota'] = $detail[0]['quota'];
@@ -161,8 +161,8 @@ class StoreBargainServices extends BaseServices
                 $valueGroup = $storeProductAttrServices->saveProductAttr($skuList, (int)$id, 2);
                 if (!$res) throw new AdminException(100007);
             } else {
-                if (!$storeProductServices->getOne(['is_show' => 1, 'is_del' => 0, 'id' => $data['product_id']])) {
-                    throw new AdminException(400091);
+                if (!$storeProductServices->getOne(['is_del' => 0, 'id' => $data['product_id']])) {
+                    throw new AdminException('无法添加回收站商品');
                 }
                 $data['add_time'] = time();
                 $res = $this->dao->save($data);
@@ -496,6 +496,7 @@ class StoreBargainServices extends BaseServices
         }
         $data['userBargainInfo'] = $userBargainInfo;
         $data['bargain']['price'] = bcsub($data['bargain']['price'], (string)$userBargainInfo['alreadyPrice'], 2);
+        $data['bargain']['product_is_show'] = app()->make(StoreProductServices::class)->value($data['bargain']['product_id'], 'is_show');
 
         //用户访问事件
         event('UserVisitListener', [$user['uid'], $id, 'bargain', $bargain['product_id'], 'view']);
@@ -631,7 +632,7 @@ class StoreBargainServices extends BaseServices
         $userHelpService = app()->make(StoreBargainUserHelpServices::class);
         /** @var StoreBargainUserServices $bargainUserService */
         $bargainUserService = app()->make(StoreBargainUserServices::class);
-        $bargainUserTableId = $bargainUserService->getBargainUserTableId($bargainId, $bargainUserUid);
+        $bargainUserTableId = $bargainUserService->getBargainUserTableId((int)$bargainId, (int)$bargainUserUid);
         if (!$bargainUserTableId) throw new ApiException(410301);
         $bargainUserInfo = $bargainUserService->get($bargainUserTableId)->toArray();
         $count = $userHelpService->isBargainUserHelpCount($bargainId, $bargainUserTableId, $uid);

+ 1 - 1
crmeb/app/services/activity/bargain/StoreBargainUserServices.php

@@ -247,7 +247,7 @@ class StoreBargainUserServices extends BaseServices
         $bargainUserHelpService = app()->make(StoreBargainUserHelpServices::class);
         $nums = $bargainUserHelpService->getNums();
         foreach ($list as &$item) {
-            $item['num'] = ($nums[$item['id']] ?? 1) - 1;
+            $item['num'] = $item['people_num'] - $nums[$item['id']];
             $item['already_num'] = $nums[$item['id']] ?? 0;
             $item['now_price'] = bcsub((string)$item['bargain_price'], (string)$item['price'], 2);
             $item['add_time'] = $item['add_time'] ? date('Y-m-d H:i:s', (int)$item['add_time']) : '';

+ 6 - 4
crmeb/app/services/activity/combination/StoreCombinationServices.php

@@ -84,7 +84,7 @@ class StoreCombinationServices extends BaseServices
         $data['start_time'] = strtotime($data['section_time'][0]);
         $data['stop_time'] = strtotime($data['section_time'][1]);
         if ($data['stop_time'] < strtotime(date('Y-m-d', time()))) throw new AdminException(400096);
-        $data['image'] = $data['images'][0];
+        $data['image'] = $data['image'];
         $data['images'] = json_encode($data['images']);
         $data['price'] = min(array_column($detail, 'price'));
         $data['quota'] = $data['quota_show'] = array_sum(array_column($detail, 'quota'));
@@ -108,8 +108,8 @@ class StoreCombinationServices extends BaseServices
                 $valueGroup = $storeProductAttrServices->saveProductAttr($skuList, (int)$id, 3);
                 if (!$res) throw new AdminException(100007);
             } else {
-                if (!$storeProductServices->getOne(['is_show' => 1, 'is_del' => 0, 'id' => $data['product_id']])) {
-                    throw new AdminException(400091);
+                if (!$storeProductServices->getOne(['is_del' => 0, 'id' => $data['product_id']])) {
+                    throw new AdminException('无法添加回收站商品');
                 }
                 $data['add_time'] = time();
                 $res = $this->dao->save($data);
@@ -378,6 +378,8 @@ class StoreCombinationServices extends BaseServices
         $storeInfo['userCollect'] = $storeProductRelationServices->isProductRelation(['uid' => $uid, 'product_id' => $id, 'type' => 'collect', 'category' => 'product']);
         $storeInfo['userLike'] = false;
         $storeInfo['store_name'] = $storeInfo['title'];
+        $storeInfo['product_is_show'] = app()->make(StoreProductServices::class)->value($storeInfo['product_id'], 'is_show');
+
 
         if (sys_config('share_qrcode', 0) && request()->isWechat()) {
             /** @var QrcodeServices $qrcodeService */
@@ -644,7 +646,7 @@ class StoreCombinationServices extends BaseServices
         $spread_count = $pinkServices->getDistinctCount([['cid', '=', $id], ['k_id', '>', 0]], 'uid', false);
         $start_count = $pinkServices->count(['cid' => $id, 'k_id' => 0]);
         $success_count = $pinkServices->count(['cid' => $id, 'k_id' => 0, 'status' => 2]);
-        $pay_price = $orderServices->sum([['combination_id', '=', $id], ['paid', '=', 1], ['refund_type', 'in', [0, 3]], ['is_del', '=', 0]], 'pay_price', false);
+        $pay_price = $orderServices->sum([['combination_id', '=', $id], ['paid', '=', 1], ['pid', '<>', -1], ['refund_type', 'in', [0, 3]], ['is_del', '=', 0]], 'pay_price', false);
         $pay_count = $orderServices->getDistinctCount([['combination_id', '=', $id], ['paid', '=', 1], ['refund_type', 'in', [0, 3]], ['is_del', '=', 0]], 'uid', false);
         return compact('people_count', 'spread_count', 'start_count', 'success_count', 'pay_price', 'pay_count');
     }

+ 2 - 2
crmeb/app/services/activity/integral/StoreIntegralServices.php

@@ -90,8 +90,8 @@ class StoreIntegralServices extends BaseServices
                 $storeProductAttrServices->saveProductAttr($skuList, (int)$id, 4);
                 if (!$res) throw new AdminException(100007);
             } else {
-                if (!$storeProductServices->getOne(['is_show' => 1, 'is_del' => 0, 'id' => $data['product_id']])) {
-                    throw new AdminException(400091);
+                if (!$storeProductServices->getOne(['is_del' => 0, 'id' => $data['product_id']])) {
+                    throw new AdminException('无法添加回收站商品');
                 }
                 $data['add_time'] = time();
                 $res = $this->dao->save($data);

+ 2 - 2
crmeb/app/services/activity/integral/StorePointRecordServices.php

@@ -190,7 +190,7 @@ class StorePointRecordServices extends BaseServices
             $list[] = [
                 'name' => $item['name'],
                 'value' => $item['value'],
-                'percent' => $count != 0 ? bcmul((string)bcdiv((string)$item['value'], (string)$count, 4), '100', 2) : 0,
+                'percent' => $count != 0 ? round(bcmul((string)bcdiv((string)$item['value'], (string)$count, 4), '100', 2), 1) : 0,
             ];
         }
         array_multisort(array_column($list, 'value'), SORT_DESC, $list);
@@ -222,7 +222,7 @@ class StorePointRecordServices extends BaseServices
             $list[] = [
                 'name' => $item['name'],
                 'value' => $item['value'],
-                'percent' => $count != 0 ? bcmul((string)bcdiv((string)$item['value'], (string)$count, 4), '100', 2) : 0,
+                'percent' => $count != 0 ? round(bcmul((string)bcdiv((string)$item['value'], (string)$count, 4), '100', 2), 1) : 0,
             ];
         }
         array_multisort(array_column($list, 'value'), SORT_DESC, $list);

+ 1 - 1
crmeb/app/services/activity/lottery/LuckLotteryRecordServices.php

@@ -213,7 +213,7 @@ class LuckLotteryRecordServices extends BaseServices
 
                         if (sys_config('pay_wechat_type')) {
                             $pay = new Pay('v3_wechat_pay');
-                            $pay->merchantPay($openid, $wechat_order_id, $prize['num'], [
+                            $pay->merchantPay($openid, $wechat_order_id, (string)$prize['num'], [
                                 'type' => $type,
                                 'batch_name' => '抽奖中奖红包',
                                 'batch_remark' => '您于' . date('Y-m-d H:i:s') . '中奖.' . $prize['num'] . '元'

+ 10 - 0
crmeb/app/services/activity/lottery/LuckLotteryServices.php

@@ -482,6 +482,16 @@ class LuckLotteryServices extends BaseServices
                 $lotteryRecordServices->receivePrize($uid, (int)$record->id);
             }
             $prize['lottery_record_id'] = $record->id;
+
+            //自定义事件-用户抽奖
+            event('CustomEventListener', ['user_lottery', [
+                'uid' => $uid,
+                'lottery_id' => $prize['lottery_id'],
+                'prize_id' => $prize['id'],
+                'record_id' => $record['id'],
+                'lottery_time' => date('Y-m-d H:i:s'),
+            ]]);
+
             return $prize;
         });
     }

+ 8 - 11
crmeb/app/services/activity/seckill/StoreSeckillServices.php

@@ -180,8 +180,8 @@ class StoreSeckillServices extends BaseServices
                 $valueGroup = $storeProductAttrServices->saveProductAttr($skuList, (int)$id, 1);
                 if (!$res) throw new AdminException(100007);
             } else {
-                if (!$storeProductServices->getOne(['is_show' => 1, 'is_del' => 0, 'id' => $data['product_id']])) {
-                    throw new AdminException(400091);
+                if (!$storeProductServices->getOne(['is_del' => 0, 'id' => $data['product_id']])) {
+                    throw new AdminException('无法添加回收站商品');
                 }
                 $data['add_time'] = time();
                 $res = $this->dao->save($data);
@@ -465,11 +465,8 @@ class StoreSeckillServices extends BaseServices
         $storeInfo['image'] = set_file_url($storeInfo['image'], $siteUrl);
         $storeInfo['image_base'] = set_file_url($storeInfo['image'], $siteUrl);
         $storeInfo['store_name'] = $storeInfo['title'];
-
-        /** @var StoreProductServices $storeProductService */
-        $storeProductService = app()->make(StoreProductServices::class);
-        $productInfo = $storeProductService->get($storeInfo['product_id']);
         $storeInfo['total'] = $storeInfo['sales'];
+        $storeInfo['product_is_show'] = app()->make(StoreProductServices::class)->value($storeInfo['product_id'], 'is_show');
 
         if (sys_config('share_qrcode', 0) && request()->isWechat()) {
             /** @var QrcodeServices $qrcodeService */
@@ -737,9 +734,9 @@ class StoreSeckillServices extends BaseServices
     {
         /** @var StoreOrderServices $orderServices */
         $orderServices = app()->make(StoreOrderServices::class);
-        $pay_count = $orderServices->getDistinctCount([['seckill_id', '=', $id], ['paid', '=', 1], ['refund_type', 'in', [0, 3]]], 'uid', false);
-        $order_count = $orderServices->getDistinctCount([['seckill_id', '=', $id], ['refund_type', 'in', [0, 3]]], 'uid', false);
-        $all_price = $orderServices->sum([['seckill_id', '=', $id], ['refund_type', 'in', [0, 3]], ['paid', '=', 1]], 'pay_price');
+        $pay_count = $orderServices->getDistinctCount([['seckill_id', '=', $id], ['pid', '<>', -1], ['paid', '=', 1], ['refund_type', 'in', [0, 3]]], 'uid', false);
+        $order_count = $orderServices->getDistinctCount([['seckill_id', '=', $id], ['pid', '<>', -1], ['refund_type', 'in', [0, 3]]], 'uid', false);
+        $all_price = $orderServices->sum([['seckill_id', '=', $id], ['pid', '<>', -1], ['refund_type', 'in', [0, 3]], ['paid', '=', 1]], 'pay_price');
         $seckillInfo = $this->dao->get($id);
         $pay_rate = $seckillInfo['quota'] . '/' . $seckillInfo['quota_show'];
         return compact('pay_count', 'order_count', 'all_price', 'pay_rate');
@@ -757,7 +754,7 @@ class StoreSeckillServices extends BaseServices
         $orderServices = app()->make(StoreOrderServices::class);
         [$page, $limit] = $this->getPageValue();
         $list = $orderServices->seckillPeople($id, $keyword, $page, $limit);
-        $count = $orderServices->getDistinctCount([['seckill_id', '=', $id], ['real_name|uid|user_phone', 'like', '%' . $keyword . '%']], 'uid', false);
+        $count = $orderServices->getDistinctCount([['seckill_id', '=', $id], ['pid', '<>', -1], ['real_name|uid|user_phone', 'like', '%' . $keyword . '%']], 'uid', false);
         foreach ($list as &$item) {
             $item['add_time'] = date('Y-m-d H:i:s', $item['add_time']);
         }
@@ -775,7 +772,7 @@ class StoreSeckillServices extends BaseServices
         /** @var StoreOrderServices $orderServices */
         $orderServices = app()->make(StoreOrderServices::class);
         [$page, $limit] = $this->getPageValue();
-        $where = $where + ['paid' => 1, 'refund_status' => 0, 'is_del' => 0];
+        $where = $where + ['paid' => 1, 'refund_status' => 0, 'is_del' => 0, 'pid' => 0];
         $list = $orderServices->seckillOrder($id, $where, $page, $limit);
         $count = $orderServices->seckillCount($id, $where);
         foreach ($list as &$item) {

+ 16 - 12
crmeb/app/services/agent/AgentLevelServices.php

@@ -67,8 +67,10 @@ class AgentLevelServices extends BaseServices
         }], $page, $limit);
         $count = $this->dao->count($where);
         foreach ($list as &$item) {
-            $item['one_brokerage_ratio'] = bcdiv(bcmul((string)sys_config('store_brokerage_ratio'), bcadd('100', (string)$item['one_brokerage'], 2), 2), '100', 2);
-            $item['two_brokerage_ratio'] = bcdiv(bcmul((string)sys_config('store_brokerage_two'), bcadd('100', (string)$item['two_brokerage'], 2), 2), '100', 2);
+//            $item['one_brokerage_ratio'] = bcdiv(bcmul((string)sys_config('store_brokerage_ratio'), bcadd('100', (string)$item['one_brokerage'], 2), 2), '100', 2);
+//            $item['two_brokerage_ratio'] = bcdiv(bcmul((string)sys_config('store_brokerage_two'), bcadd('100', (string)$item['two_brokerage'], 2), 2), '100', 2);
+            $item['one_brokerage_ratio'] = $item['one_brokerage_percent'];
+            $item['two_brokerage_ratio'] = $item['two_brokerage_percent'];
         }
         return compact('count', 'list');
     }
@@ -229,22 +231,24 @@ class AgentLevelServices extends BaseServices
         if ($one_agent_level) {
             $oneLevelInfo = $this->getLevelInfo($one_agent_level);
             if ($oneLevelInfo) {
-                if ($oneLevelInfo['one_brokerage_percent'] == '0.00') {
-                    $storeBrokerageRatio = $storeBrokerageRatio + (($storeBrokerageRatio * $oneLevelInfo['one_brokerage'] ?? 0) / 100);
-                } else {
-                    $storeBrokerageRatio = $oneLevelInfo['one_brokerage_percent'];
-                }
+                $storeBrokerageRatio = $oneLevelInfo['one_brokerage_percent'];
+//                if ($oneLevelInfo['one_brokerage_percent'] == '0.00') {
+//                    $storeBrokerageRatio = $storeBrokerageRatio + (($storeBrokerageRatio * $oneLevelInfo['one_brokerage'] ?? 0) / 100);
+//                } else {
+//                    $storeBrokerageRatio = $oneLevelInfo['one_brokerage_percent'];
+//                }
             }
         }
 
         if ($two_agent_level) {
             $twoLevelInfo = $this->getLevelInfo($two_agent_level);
             if ($twoLevelInfo) {
-                if ($twoLevelInfo['two_brokerage_percent'] == '0.00') {
-                    $storeBrokerageTwo = $storeBrokerageTwo + (($storeBrokerageTwo * $twoLevelInfo['two_brokerage'] ?? 0) / 100);
-                } else {
-                    $storeBrokerageTwo = $twoLevelInfo['two_brokerage_percent'];
-                }
+                $storeBrokerageTwo = $twoLevelInfo['two_brokerage_percent'];
+//                if ($twoLevelInfo['two_brokerage_percent'] == '0.00') {
+//                    $storeBrokerageTwo = $storeBrokerageTwo + (($storeBrokerageTwo * $twoLevelInfo['two_brokerage'] ?? 0) / 100);
+//                } else {
+//                    $storeBrokerageTwo = $twoLevelInfo['two_brokerage_percent'];
+//                }
             }
         }
 

+ 23 - 17
crmeb/app/services/agent/DivisionServices.php

@@ -29,7 +29,7 @@ class DivisionServices extends BaseServices
     {
         /** @var UserServices $userServices */
         $userServices = app()->make(UserServices::class);
-        $data = $userServices->getDivisionList($where + ['status' => 1], 'uid,nickname,avatar,division_percent,division_end_time,division_status,division_invite');
+        $data = $userServices->getDivisionList($where + ['status' => 1], 'uid,nickname,avatar,division_name,division_percent,division_end_time,division_status,division_invite');
         foreach ($data['list'] as &$item) {
             $item['division_end_time'] = date('Y-m-d', $item['division_end_time']);
             $item['agent_count'] = $userServices->count([
@@ -62,7 +62,7 @@ class DivisionServices extends BaseServices
         ];
         $where['status'] = 1;
         $where['is_del'] = 0;
-        $data = $userServices->getDivisionList($where, 'uid,nickname,avatar,division_percent,division_end_time,division_status');
+        $data = $userServices->getDivisionList($where, 'uid,nickname,avatar,division_name,division_percent,division_end_time,division_status');
         foreach ($data['list'] as &$item) {
             $item['agent_count'] = $userServices->count([
                 'agent_id' => $item['uid'],
@@ -98,10 +98,11 @@ class DivisionServices extends BaseServices
         }
         $field = [];
         $title = '事业部';
+        $field[] = Form::input('division_name', '事业部名称', $userInfo['division_name'] ?? '')->required('请输入事业部名称');
         if ($uid) {
             $field[] = Form::hidden('uid', $uid);
         } else {
-            $field[] = Form::frameImage('image', '用户', $this->url(config('app.admin_prefix', 'admin') . '/system.user/list', ['fodder' => 'image'], true))->icon('el-icon-user')->width('950px')->height('560px')->Props(['srcKey' => 'image', 'footer' => false]);
+            $field[] = Form::frameImage('image', '关联用户', $this->url(config('app.admin_prefix', 'admin') . '/system.user/list', ['fodder' => 'image'], true))->icon('el-icon-user')->width('950px')->height('560px')->Props(['srcKey' => 'image', 'footer' => false]);
         }
         $field[] = Form::hidden('aid', $adminInfo['id'] ?? 0);
         $field[] = Form::number('division_percent', '佣金比例', $userInfo['division_percent'] ?? '')->placeholder('区域代理佣金比例1-100')->info('填写1-100,如填写50代表返佣50%')->style(['width' => '173px'])->min(0)->max(100)->required();
@@ -110,7 +111,6 @@ class DivisionServices extends BaseServices
         $field[] = Form::input('account', '管理账号', $adminInfo['account'] ?? '')->required('请填写管理员账号');
         $field[] = Form::input('pwd', '管理密码')->type('password')->placeholder('请填写管理员密码');
         $field[] = Form::input('conf_pwd', '确认密码')->type('password')->placeholder('请输入确认密码');
-        $field[] = Form::input('real_name', '代理姓名', $adminInfo['real_name'] ?? '')->required('请输入管理员姓名');
         /** @var SystemRoleServices $service */
         $service = app()->make(SystemRoleServices::class);
         $options = $service->getRoleFormSelect(1);
@@ -129,11 +129,13 @@ class DivisionServices extends BaseServices
         if ((int)$data['uid'] == 0) throw new AdminException(400450);
         /** @var UserServices $userServices */
         $userServices = app()->make(UserServices::class);
-        $userInfo = $userServices->getUserInfo($data['uid'], 'is_division,is_agent,is_staff');
-        if (!$userInfo) throw new AdminException('用户不存在');
-        if ($userInfo['is_division']) throw new AdminException('此用户是事业部,请勿重复添加');
-        if ($userInfo['is_agent']) throw new AdminException('此用户是代理商,无法添加为事业部');
-        if ($userInfo['is_staff']) throw new AdminException('此用户是下级员工,无法添加为事业部');
+        if ($data['aid'] == 0) {
+            $userInfo = $userServices->getUserInfo($data['uid'], 'is_division,is_agent,is_staff');
+            if (!$userInfo) throw new AdminException('用户不存在');
+            if ($userInfo['is_division']) throw new AdminException('此用户是事业部,请勿重复添加');
+            if ($userInfo['is_agent']) throw new AdminException('此用户是代理商,无法添加为事业部');
+            if ($userInfo['is_staff']) throw new AdminException('此用户是下级员工,无法添加为事业部');
+        }
         $uid = $data['uid'];
         $aid = $data['aid'];
         $agentData = [
@@ -149,13 +151,14 @@ class DivisionServices extends BaseServices
             'division_type' => 1,
             'division_status' => $data['division_status'],
             'spread_uid' => 0,
-            'spread_time' => 0
+            'spread_time' => 0,
+            'division_name' => $data['division_name']
         ];
         $adminData = [
             'account' => $data['account'],
             'pwd' => $data['pwd'],
             'conf_pwd' => $data['conf_pwd'],
-            'real_name' => $data['real_name'],
+            'real_name' => $data['division_name'],
             'roles' => $data['roles'],
             'status' => 1,
             'level' => 1,
@@ -235,16 +238,17 @@ class DivisionServices extends BaseServices
         if ($uid && !$userInfo) throw new AdminException(400214);
         $field = [];
         $options = [];
-        $divisionList = $userService->getDivisionList(['status' => 1, 'division_type' => 1], 'uid,nickname');
+        $divisionList = $userService->getDivisionList(['status' => 1, 'division_type' => 1], 'uid,division_name');
         foreach ($divisionList['list'] as $item) {
-            $options[] = ['value' => $item['uid'], 'label' => $item['nickname']];
+            $options[] = ['value' => $item['uid'], 'label' => $item['division_name']];
         }
+        $field[] = Form::input('division_name', '代理商名称', $userInfo['division_name'] ?? '')->required('请输入代理商名称');
         if ($uid) {
             $field[] = Form::hidden('uid', $uid);
             $field[] = Form::hidden('edit', 1);
         } else {
-            $field[] = Form::select('division_id', '事业部', $info['file_name'] ?? '')->setOptions(Form::setOptions($options))->filterable(1);
-            $field[] = Form::frameImage('image', '代理商', $this->url(config('app.admin_prefix', 'admin') . '/system.user/list', ['fodder' => 'image'], true))->icon('el-icon-user')->width('950px')->height('560px')->Props(['srcKey' => 'image', 'footer' => false]);
+            $field[] = Form::select('division_id', '上级事业部', $info['file_name'] ?? '')->setOptions(Form::setOptions($options))->filterable(1);
+            $field[] = Form::frameImage('image', '关联用户', $this->url(config('app.admin_prefix', 'admin') . '/system.user/list', ['fodder' => 'image'], true))->icon('el-icon-user')->width('950px')->height('560px')->Props(['srcKey' => 'image', 'footer' => false]);
             $field[] = Form::hidden('edit', 0);
         }
         $field[] = Form::number('division_percent', '佣金比例', $userInfo['division_percent'] ?? '')->placeholder('代理商佣金比例1-100')->info('填写1-100,如填写50代表返佣50%,但是不能高于上级事业部的比例')->style(['width' => '173px'])->min(0)->max(100)->required();
@@ -278,7 +282,8 @@ class DivisionServices extends BaseServices
             'is_agent' => 1,
             'agent_id' => $uid,
             'is_staff' => 0,
-            'staff_id' => 0
+            'staff_id' => 0,
+            'division_name' => $data['division_name'],
         ];
         $division_info = $userServices->getUserInfo($data['division_id'], 'division_end_time,division_percent');
         if ($division_info) {
@@ -430,10 +435,11 @@ class DivisionServices extends BaseServices
         if ($agentCode && !$agentId) {
             /** @var QrcodeServices $qrCode */
             $qrCode = app()->make(QrcodeServices::class);
-            if ($info = $qrCode->getOne(['id' => $agentCode, 'status' => 1])) {
+            if ($info = $qrCode->getOne(['id' => $agentCode, 'third_type' => 'agent', 'status' => 1])) {
                 $agentId = $info['third_id'];
             }
         }
+        if (!$agentId) return false;
         if ($uid == $agentId) return '自己不能推荐自己';
         /** @var UserServices $userServices */
         $userServices = app()->make(UserServices::class);

+ 28 - 9
crmeb/app/services/article/ArticleServices.php

@@ -19,7 +19,6 @@ use crmeb\exceptions\AdminException;
 /**
  * Class ArticleServices
  * @package app\services\article
- * @method cidByArticleList(array $where, int $page, int $limit, string $field)
  */
 class ArticleServices extends BaseServices
 {
@@ -38,18 +37,22 @@ class ArticleServices extends BaseServices
      * @param int $page
      * @param int $limit
      * @return array
+     * @throws \ReflectionException
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
      */
     public function getList(array $where, int $page = 0, int $limit = 0)
     {
         if (!$page && !$limit) {
             [$page, $limit] = $this->getPageValue();
         }
-        /** @var WechatNewsCategoryServices $services */
-        $services = app()->make(WechatNewsCategoryServices::class);
-        $where['ids'] = $services->getNewIds();
+        $where['ids'] = app()->make(WechatNewsCategoryServices::class)->getNewIds();
         $list = $this->dao->getList($where, $page, $limit);
         foreach ($list as &$item) {
             $item['store_name'] = $item['storeInfo']['store_name'] ?? '';
+            $item['copy_url'] = sys_config('site_url') . '/pages/extension/news_details/index?id=' . $item['id'];
+            $item['copy_url_pc'] = sys_config('site_url') . '/news_detail?id=' . $item['id'];
         }
         $count = $this->dao->count($where);
         return compact('list', 'count');
@@ -89,9 +92,13 @@ class ArticleServices extends BaseServices
     }
 
     /**
-     * 获取商品详情
-     * @param $id
+     * 获取文章详情
+     * @param int $id
      * @return array
+     * @throws \ReflectionException
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
      */
     public function read(int $id)
     {
@@ -101,7 +108,7 @@ class ArticleServices extends BaseServices
     }
 
     /**
-     * 删除商品
+     * 删除文章
      * @param int $id
      */
     public function del(int $id)
@@ -139,9 +146,14 @@ class ArticleServices extends BaseServices
         return $this->search($where, $search)->count();
     }
 
-    /**获取一条数据
+    /**
+     * 获取一条数据
      * @param int $id
      * @return mixed
+     * @throws \ReflectionException
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
      */
     public function getInfo(int $id)
     {
@@ -161,15 +173,22 @@ class ArticleServices extends BaseServices
      * 获取文章列表
      * @param $new_id
      * @return int
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
      */
     public function articleList($new_id)
     {
         return $this->dao->articleLists($new_id);
     }
 
-    /**图文详情
+    /**
+     * 图文详情
      * @param $new_id
      * @return mixed
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
      */
     public function articlesList($new_id)
     {

+ 13 - 19
crmeb/app/services/message/SystemNotificationServices.php

@@ -136,19 +136,19 @@ class SystemNotificationServices extends BaseServices
         ],
 
         //订单发起退款
-//        'order_initiated_refund' => [
-//            ['label' => '用户uid', 'value' => 'uid'],
-//            ['label' => '订单order_id', 'value' => 'order_id'],
-//            ['label' => '用户名称', 'value' => 'real_name'],
-//            ['label' => '用户电话', 'value' => 'user_phone'],
-//            ['label' => '用户地址', 'value' => 'user_address'],
-//            ['label' => '商品总数', 'value' => 'total_num'],
-//            ['label' => '支付金额', 'value' => 'pay_price'],
-//            ['label' => '支付邮费', 'value' => 'pay_postage'],
-//            ['label' => '积分抵扣金额', 'value' => 'deduction_price'],
-//            ['label' => '优惠券抵扣金额', 'value' => 'coupon_price'],
-//            ['label' => '支付类型', 'value' => 'pay_type'],
-//        ],
+        'order_initiated_refund' => [
+            ['label' => '用户uid', 'value' => 'uid'],
+            ['label' => '订单order_id', 'value' => 'order_id'],
+            ['label' => '用户名称', 'value' => 'real_name'],
+            ['label' => '用户电话', 'value' => 'user_phone'],
+            ['label' => '用户地址', 'value' => 'user_address'],
+            ['label' => '商品总数', 'value' => 'total_num'],
+            ['label' => '支付金额', 'value' => 'pay_price'],
+            ['label' => '支付邮费', 'value' => 'pay_postage'],
+            ['label' => '积分抵扣金额', 'value' => 'deduction_price'],
+            ['label' => '优惠券抵扣金额', 'value' => 'coupon_price'],
+            ['label' => '支付类型', 'value' => 'pay_type'],
+        ],
 
         //订单成功退款
         'order_refund_success' => [
@@ -306,12 +306,6 @@ class SystemNotificationServices extends BaseServices
             ['value' => 'extract_fail', 'label' => '提现失败场景'],
             ['value' => 'brokerage_received', 'label' => '佣金到账场景'],
             ['value' => 'point_received', 'label' => '积分到账场景'],
-//            ['value' => 'login_success', 'label' => '砍价成功场景'],
-//            ['value' => 'login_success', 'label' => '开团成功场景'],
-//            ['value' => 'login_success', 'label' => '参团成功场景'],
-//            ['value' => 'login_success', 'label' => '拼团成功场景'],
-//            ['value' => 'login_success', 'label' => '拼团失败场景'],
-//            ['value' => 'login_success', 'label' => '取消拼团场景'],
         ];
         $field = [];
         $field[] = Form::select('custom_trigger', '触发位置', $info['custom_trigger'] ?? '')->options($data);

+ 1 - 1
crmeb/app/services/message/notice/EnterpriseWechatService.php

@@ -48,7 +48,7 @@ class EnterpriseWechatService extends NoticeService
      */
     public function weComSend($data)
     {
-        if ($this->isOpen) {
+        if ($this->noticeInfo['is_ent_wechat'] == 1 && $this->noticeInfo['url'] !== '') {
             $url = $this->noticeInfo['url'];
             $ent_wechat_text = $this->noticeInfo['ent_wechat_text'];
             try {

+ 1 - 1
crmeb/app/services/order/OtherOrderServices.php

@@ -348,7 +348,7 @@ class OtherOrderServices extends BaseServices
 
         $orderInfo['pay_type'] = $paytype;
         // 小程序订单服务
-        event('OrderShipping', ['member', $orderInfo, 3, '', '']);
+        event('OrderShippingListener', ['member', $orderInfo, 3, '', '']);
         return false !== $res;
     }
 

+ 18 - 6
crmeb/app/services/order/StoreCartServices.php

@@ -279,6 +279,15 @@ class StoreCartServices extends BaseServices
         } else {//加入购物车记录
             ProductLogJob::dispatch(['cart', ['uid' => $uid, 'product_id' => $product_id, 'cart_num' => $cart_num]]);
             $cart = $this->dao->getOne(['type' => $type, 'uid' => $uid, 'product_id' => $product_id, 'product_attr_unique' => $product_attr_unique, 'is_del' => 0, 'is_new' => 0, 'is_pay' => 0, 'status' => 1]);
+
+            //自定义事件-加入购物车
+            event('CustomEventListener', ['user_add_cart', [
+                'product_id' => $product_id,
+                'uid' => $uid,
+                'cart_num' => $cart_num,
+                'add_time' => date('Y-m-d H:i:s'),
+            ]]);
+
             if ($cart) {
                 $cart->cart_num = $cart_num + $cart->cart_num;
                 $cart->add_time = time();
@@ -288,7 +297,6 @@ class StoreCartServices extends BaseServices
                 $add_time = time();
                 return $this->dao->save(compact('uid', 'product_id', 'cart_num', 'product_attr_unique', 'type', 'add_time'))->id;
             }
-
         }
     }
 
@@ -326,7 +334,8 @@ class StoreCartServices extends BaseServices
             throw new ApiException('不能小于起购数量');
         }
         if ($limitInfo['is_limit']) {
-            if ($limitInfo['limit_type'] == 1 && $number > $limitInfo['limit_num']) {
+            $num = $this->dao->sum([['uid', '=', $uid], ['product_id', '=', $carInfo->product_id], ['id', '<>', $id]], 'cart_num') + $number;
+            if ($limitInfo['limit_type'] == 1 && $num > $limitInfo['limit_num']) {
                 throw new ApiException(410239, ['limit' => $limitInfo['limit_num']]);
             } else if ($limitInfo['limit_type'] == 2) {
                 /** @var StoreOrderCartInfoServices $orderCartServices */
@@ -334,7 +343,7 @@ class StoreCartServices extends BaseServices
                 $orderPayNum = $orderCartServices->sum(['uid' => $uid, 'product_id' => $carInfo->product_id], 'cart_num');
                 $orderRefundNum = $orderCartServices->sum(['uid' => $uid, 'product_id' => $carInfo->product_id], 'refund_num');
                 $orderNum = $orderPayNum - $orderRefundNum;
-                if (($number + $orderNum) > $limitInfo['limit_num']) {
+                if (($num + $orderNum) > $limitInfo['limit_num']) {
                     throw new ApiException(410240, ['limit' => $limitInfo['limit_num'], 'pay_num' => $orderNum]);
                 }
             }
@@ -463,13 +472,14 @@ class StoreCartServices extends BaseServices
         }
 
         $cart = $this->dao->getOne(['uid' => $uid, 'product_id' => $productId, 'product_attr_unique' => $unique]);
+        $min_qty = $productServices->value(['id' => $productId], 'min_qty');
         if ($cart) {
             if ($type == -1) {
                 $cart->cart_num = $num;
             } elseif ($type == 0) {
                 $cart->cart_num = $cart->cart_num - $num;
-                if ($cart->cart_num < $productServices->value(['id' => $productId], 'min_qty')) {
-                    throw new ApiException('不能小于起购数量');
+                if ($cart->cart_num < $min_qty) {
+                    return $this->dao->delete($cart->id);
                 }
             } elseif ($type == 1) {
                 $cart->cart_num = $cart->cart_num + $num;
@@ -482,10 +492,11 @@ class StoreCartServices extends BaseServices
                 return $cart->id;
             }
         } else {
+
             $data = [
                 'uid' => $uid,
                 'product_id' => $productId,
-                'cart_num' => $num,
+                'cart_num' => $num > $min_qty ? $num : $min_qty,
                 'product_attr_unique' => $unique,
                 'type' => 0,
                 'add_time' => time()
@@ -605,6 +616,7 @@ class StoreCartServices extends BaseServices
         $productServices = app()->make(StoreProductServices::class);
         $valid = $invalid = [];
         foreach ($cartList as &$item) {
+            if ($item['type'] == 0) $item['min_qty'] = $item['productInfo']['min_qty'];
             $item['productInfo']['express_delivery'] = false;
             $item['productInfo']['store_mention'] = false;
             if (isset($item['productInfo']['logistics'])) {

+ 1 - 0
crmeb/app/services/order/StoreOrderCartInfoServices.php

@@ -203,6 +203,7 @@ class StoreOrderCartInfoServices extends BaseServices
                     $item['cart_num'] = $item['cart_info']['cart_num'] ?? 0;
                 }
             }
+            $item['num'] = 1;
         }
         return $cartInfo;
     }

+ 18 - 0
crmeb/app/services/order/StoreOrderCreateServices.php

@@ -312,6 +312,24 @@ class StoreOrderCreateServices extends BaseServices
         event('OrderCreateAfterListener', [$order, compact('cartInfo', 'priceData', 'addressId', 'cartIds', 'news'), $uid, $key, $combinationId, $seckillId, $bargainId]);
         // 推送订单
         event('OutPushListener', ['order_create_push', ['order_id' => (int)$order['id']]]);
+
+        //自定义事件-订单创建事件
+        event('CustomEventListener', ['order_create', [
+            'uid' => $uid,
+            'id' => (int)$order['id'],
+            'order_id' => $order['order_id'],
+            'real_name' => $order['real_name'],
+            'user_phone' => $order['user_phone'],
+            'user_address' => $order['user_address'],
+            'total_num' => $order['total_num'],
+            'pay_price' => $order['pay_price'],
+            'pay_postage' => $order['pay_postage'],
+            'deduction_price' => $order['deduction_price'],
+            'coupon_price' => $order['coupon_price'],
+            'store_name' => app()->make(StoreOrderCartInfoServices::class)->getCarIdByProductTitle((int)$order['id']),
+            'add_time' => date('Y-m-d H:i:s', $order['add_time']),
+        ]]);
+
         return $order;
     }
 

+ 14 - 1
crmeb/app/services/order/StoreOrderDeliveryServices.php

@@ -489,9 +489,22 @@ class StoreOrderDeliveryServices extends BaseServices
             $data['delivery_id'] = uniqid();
         }
         // 小程序订单管理
-        event('OrderShipping', ['product', $orderInfo, $type, $data['delivery_id'], $data['delivery_name']]);
+        event('OrderShippingListener', ['product', $orderInfo, $type, $data['delivery_id'], $data['delivery_name']]);
         //到期自动收货
         event('OrderDeliveryListener', [$orderInfo, $storeName, $data, $type]);
+
+        //自定义事件-订单发货
+        event('CustomEventListener', ['admin_order_express', [
+            'uid' => $orderInfo['uid'],
+            'real_name' => $orderInfo['real_name'],
+            'user_phone' => $orderInfo['user_phone'],
+            'user_address' => $orderInfo['user_address'],
+            'order_id' => $orderInfo['order_id'],
+            'delivery_name' => $orderInfo['delivery_name'],
+            'delivery_id' => $orderInfo['delivery_id'],
+            'express_time' => date('Y-m-d H:i:s'),
+        ]]);
+
         return $res;
     }
 

+ 394 - 217
crmeb/app/services/order/StoreOrderInvoiceServices.php

@@ -1,217 +1,394 @@
-<?php
-// +----------------------------------------------------------------------
-// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
-// +----------------------------------------------------------------------
-// | Copyright (c) 2016~2023 https://www.crmeb.com All rights reserved.
-// +----------------------------------------------------------------------
-// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
-// +----------------------------------------------------------------------
-// | Author: CRMEB Team <admin@crmeb.com>
-// +----------------------------------------------------------------------
-declare (strict_types=1);
-
-namespace app\services\order;
-
-
-use app\services\BaseServices;
-use crmeb\exceptions\ApiException;
-use app\dao\order\StoreOrderInvoiceDao;
-use app\services\user\UserInvoiceServices;
-
-
-/**
- * Class StoreOrderInvoiceServices
- * @package app\services\order
- */
-class StoreOrderInvoiceServices extends BaseServices
-{
-    /**
-     * LiveAnchorServices constructor.
-     * @param StoreOrderInvoiceDao $dao
-     */
-    public function __construct(StoreOrderInvoiceDao $dao)
-    {
-        $this->dao = $dao;
-    }
-
-    public function chart(array $where)
-    {
-        $where['is_pay'] = 1;
-        //全部
-        $data['all'] = (string)$this->dao->count($where);
-        //待开
-        $where['type'] = 1;
-        $data['noOpened'] = (string)$this->dao->count($where);
-        //已开
-        $where['type'] = 2;
-        $data['opened'] = (string)$this->dao->count($where);
-        //退款
-        $where['type'] = 3;
-        $data['refund'] = (string)$this->dao->count($where);
-        return $data;
-    }
-
-    /**
-     * 后台获取开票列表
-     * @param array $where
-     * @return array
-     * @throws \think\db\exception\DataNotFoundException
-     * @throws \think\db\exception\DbException
-     * @throws \think\db\exception\ModelNotFoundException
-     */
-    public function getList(array $where)
-    {
-        [$page, $list] = $this->getPageValue();
-        $field = 'id as invoice_id,order_id,header_type,type,name,duty_number,drawer_phone,email,tell,address,bank,card_number,is_invoice,invoice_number,remark as invoice_reamrk,invoice_time,add_time as invoice_add_time';
-        $where['is_pay'] = 1;
-        $list = $this->dao->getList($where, $field, ['order' => function ($query) {
-            $query->field('id,order_id,pay_price,add_time,real_name,user_phone,status,refund_status');
-        }], 'add_time desc', $page, $list);
-        foreach ($list as &$item) {
-            $item['id'] = $item['order']['id'] ?? 0;
-            $item['order_id'] = $item['order']['order_id'] ?? '';
-            $item['pay_price'] = $item['order']['pay_price'] ?? 0.00;
-            $item['real_name'] = $item['order']['real_name'] ?? '';
-            $item['user_phone'] = $item['order']['user_phone'] ?? '';
-            $item['status'] = $item['order']['status'] ?? '';
-            $item['refund_status'] = $item['order']['refund_status'] ?? 0;
-            $item['add_time'] = date('Y-m-d H:i:s', $item['order']['add_time'] ?? $item['invoice_add_time'] ?? time());
-            $item['invoice_add_time'] = date('Y-m-d H:i:s', $item['invoice_add_time']);
-        }
-        $count = $this->dao->count($where);
-        return compact('list', 'count');
-    }
-
-    /**
-     * 前端获取开票列表(带商品信息)
-     * @param $where
-     * @return array
-     */
-    public function getOrderInvoiceList(array $where)
-    {
-        [$page, $list] = $this->getPageValue();
-        $where['is_pay'] = 1;
-        $list = $this->dao->getList($where, '*', ['order'], 'add_time desc', $page, $list);
-        /** @var StoreOrderServices $storeOrderServices */
-        $storeOrderServices = app()->make(StoreOrderServices::class);
-        foreach ($list as &$item) {
-            if (isset($item['order']) && $item['order']) {
-                $item['order'] = $storeOrderServices->tidyOrder($item['order'], true);
-                if (isset($item['order']['_status']['_type']) && $item['order']['_status']['_type'] == 3) {
-                    foreach ($item['order']['cartInfo'] ?: [] as $key => $product) {
-                        $item['order']['cartInfo'][$key]['add_time'] = isset($product['add_time']) ? date('Y-m-d H:i', (int)$product['add_time']) : '时间错误';
-                    }
-                }
-            }
-        }
-        return $list;
-    }
-
-    /**
-     * 订单申请开票
-     * @param int $uid
-     * @param $order_id
-     * @param int $invoice_id
-     * @return mixed
-     * @throws \think\db\exception\DataNotFoundException
-     * @throws \think\db\exception\DbException
-     * @throws \think\db\exception\ModelNotFoundException
-     */
-    public function makeUp(int $uid, $order_id, int $invoice_id)
-    {
-        if (!$order_id) throw new ApiException(100100);
-        if (!$invoice_id) throw new ApiException(410325);
-
-        /** @var StoreOrderServices $storeOrderServices */
-        $storeOrderServices = app()->make(StoreOrderServices::class);
-        /** @var UserInvoiceServices $userInvoiceServices */
-        $userInvoiceServices = app()->make(UserInvoiceServices::class);
-        $order = $storeOrderServices->getOne(['order_id|id' => $order_id, 'is_del' => 0]);
-        if (!$order) {
-            throw new ApiException(410173);
-        }
-        //检测再带查询
-        $invoice = $userInvoiceServices->checkInvoice($invoice_id, $uid);
-
-        if ($this->dao->getOne(['order_id' => $order['id'], 'uid' => $uid])) {
-            throw new ApiException(410249);
-        }
-        if ($order['refund_status'] == 2) {
-            throw new ApiException(410226);
-        }
-        if ($order['refund_status'] == 1) {
-            throw new ApiException(410250);
-        }
-        unset($invoice['id'], $invoice['add_time']);
-        $data = [];
-        $data['category'] = 'order';
-        $data['order_id'] = $order['id'];
-        $data['invoice_id'] = $invoice_id;
-        $data['add_time'] = time();
-        $data['is_pay'] = $order['paid'] == 1 ? 1 : 0;
-        $data = array_merge($data, $invoice);
-        if (!$re = $this->dao->save($data)) {
-            throw new ApiException(410251);
-        }
-        return ['id' => $re->id];
-    }
-
-    public function setInvoice(int $id, array $data)
-    {
-        $orderInvoice = $this->dao->get($id);
-        if (!$orderInvoice) {
-            throw new ApiException(100026);
-        }
-        if ($data['is_invoice'] == 1) {
-            $data['invoice_time'] = time();
-        }
-        if (!$this->dao->update($id, $data, 'id')) {
-            throw new ApiException(100015);
-        }
-        return true;
-    }
-
-    /**
-     * 拆分订单同步拆分申请开票记录
-     * @param int $oid
-     * @return bool
-     * @throws \think\db\exception\DataNotFoundException
-     * @throws \think\db\exception\DbException
-     * @throws \think\db\exception\ModelNotFoundException
-     */
-    public function splitOrderInvoice(int $oid)
-    {
-        /** @var StoreOrderServices $storeOrderServices */
-        $storeOrderServices = app()->make(StoreOrderServices::class);
-        $orderInfo = $storeOrderServices->getOne(['id' => $oid, 'is_del' => 0]);
-        if (!$orderInfo) {
-            throw new ApiException(410173);
-        }
-        $pid = $orderInfo['pid'] > 0 ? $orderInfo['pid'] : $orderInfo['id'];
-        //查询开票记录
-        $orderInvoice = $this->dao->get(['order_id' => $oid]);
-        //查询子订单
-        $spliteOrder = $storeOrderServices->getColumn(['pid' => $pid, 'is_system_del' => 0], 'id,order_id');
-        if ($spliteOrder && $orderInvoice) {
-            $data = $orderInvoice->toArray();
-            unset($data['id']);
-            $data['add_time'] = strtotime($data['add_time']);
-            $data_all = [];
-            foreach ($spliteOrder as $order) {
-                if (!$this->dao->count(['order_id' => $order['id']])) {
-                    $data['order_id'] = $order['id'];
-                    $data_all[] = $data;
-                }
-            }
-            if ($data_all) {
-                $this->transaction(function () use ($data_all, $orderInvoice, $orderInfo) {
-                    $this->dao->saveAll($data_all);
-                    if ($orderInfo['pid'] <= 0) {
-                        $this->dao->delete(['id' => $orderInvoice['id']]);
-                    }
-                });
-            }
-        }
-        return true;
-    }
-}
+<?php
+// +----------------------------------------------------------------------
+// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2016~2023 https://www.crmeb.com All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
+// +----------------------------------------------------------------------
+// | Author: CRMEB Team <admin@crmeb.com>
+// +----------------------------------------------------------------------
+declare (strict_types=1);
+
+namespace app\services\order;
+
+
+use app\jobs\OrderInvoiceJob;
+use app\services\BaseServices;
+use app\services\serve\ServeServices;
+use crmeb\exceptions\AdminException;
+use crmeb\exceptions\ApiException;
+use app\dao\order\StoreOrderInvoiceDao;
+use app\services\user\UserInvoiceServices;
+use think\facade\Log;
+
+
+/**
+ * Class StoreOrderInvoiceServices
+ * @package app\services\order
+ */
+class StoreOrderInvoiceServices extends BaseServices
+{
+    /**
+     * LiveAnchorServices constructor.
+     * @param StoreOrderInvoiceDao $dao
+     */
+    public function __construct(StoreOrderInvoiceDao $dao)
+    {
+        $this->dao = $dao;
+    }
+
+    public function chart(array $where)
+    {
+        $where['is_pay'] = 1;
+        $where['is_del'] = 0;
+        //全部
+        $data['all'] = (string)$this->dao->count($where);
+        //待开
+        $where['type'] = 1;
+        $data['noOpened'] = (string)$this->dao->count($where);
+        //已开
+        $where['type'] = 2;
+        $data['opened'] = (string)$this->dao->count($where);
+        //退款
+        $where['type'] = 3;
+        $data['refund'] = (string)$this->dao->count($where);
+        $data['elec_invoice'] = (int)sys_config('elec_invoice', 0);
+        return $data;
+    }
+
+    /**
+     * 后台获取开票列表
+     * @param array $where
+     * @return array
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     */
+    public function getList(array $where)
+    {
+        [$page, $list] = $this->getPageValue();
+        $field = 'id as invoice_id,order_id,header_type,type,name,duty_number,drawer_phone,email,tell,address,bank,card_number,is_invoice,invoice_number,remark as invoice_reamrk,invoice_time,add_time as invoice_add_time,unique_num,invoice_num,invoice_type,invoice_serial_number,red_invoice_num';
+        $where['is_pay'] = 1;
+        $where['is_del'] = 0;
+        $list = $this->dao->getList($where, $field, ['order' => function ($query) {
+            $query->field('id,order_id,pay_price,add_time,real_name,user_phone,status,refund_status');
+        }], 'add_time desc', $page, $list);
+        foreach ($list as &$item) {
+            $item['id'] = $item['order']['id'] ?? 0;
+            $item['order_id'] = $item['order']['order_id'] ?? '';
+            $item['pay_price'] = $item['order']['pay_price'] ?? 0.00;
+            $item['real_name'] = $item['order']['real_name'] ?? '';
+            $item['user_phone'] = $item['order']['user_phone'] ?? '';
+            $item['status'] = $item['order']['status'] ?? '';
+            $item['refund_status'] = $item['order']['refund_status'] ?? 0;
+            $item['add_time'] = date('Y-m-d H:i:s', $item['order']['add_time'] ?? $item['invoice_add_time'] ?? time());
+            $item['invoice_add_time'] = date('Y-m-d H:i:s', $item['invoice_add_time']);
+        }
+        $count = $this->dao->count($where);
+        return compact('list', 'count');
+    }
+
+    /**
+     * 前端获取开票列表(带商品信息)
+     * @param $where
+     * @return array
+     */
+    public function getOrderInvoiceList(array $where)
+    {
+        [$page, $list] = $this->getPageValue();
+        $where['is_pay'] = 1;
+        $where['is_del'] = 0;
+        $list = $this->dao->getList($where, '*', ['order'], 'add_time desc', $page, $list);
+        /** @var StoreOrderServices $storeOrderServices */
+        $storeOrderServices = app()->make(StoreOrderServices::class);
+        foreach ($list as &$item) {
+            if (isset($item['order']) && $item['order']) {
+                $item['order'] = $storeOrderServices->tidyOrder($item['order'], true);
+                if (isset($item['order']['_status']['_type']) && $item['order']['_status']['_type'] == 3) {
+                    foreach ($item['order']['cartInfo'] ?: [] as $key => $product) {
+                        $item['order']['cartInfo'][$key]['add_time'] = isset($product['add_time']) ? date('Y-m-d H:i', (int)$product['add_time']) : '时间错误';
+                    }
+                }
+            }
+        }
+        return $list;
+    }
+
+    /**
+     * 订单申请开票
+     * @param int $uid
+     * @param $order_id
+     * @param int $invoice_id
+     * @return mixed
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     */
+    public function makeUp(int $uid, $order_id, int $invoice_id)
+    {
+        if (!$order_id) throw new AdminException(100100);
+        if (!$invoice_id) throw new AdminException(410325);
+
+        /** @var StoreOrderServices $storeOrderServices */
+        $storeOrderServices = app()->make(StoreOrderServices::class);
+        /** @var UserInvoiceServices $userInvoiceServices */
+        $userInvoiceServices = app()->make(UserInvoiceServices::class);
+        $order = $storeOrderServices->getOne(['order_id|id' => $order_id, 'is_del' => 0]);
+        if (!$order) {
+            throw new AdminException(410173);
+        }
+        //检测再带查询
+        $invoice = $userInvoiceServices->checkInvoice($invoice_id, $uid);
+
+        if ($this->dao->getOne(['order_id' => $order['id'], 'uid' => $uid])) {
+            throw new AdminException(410249);
+        }
+        if ($order['refund_status'] == 2) {
+            throw new AdminException(410226);
+        }
+        if ($order['refund_status'] == 1) {
+            throw new AdminException(410250);
+        }
+        unset($invoice['id'], $invoice['add_time']);
+        $data = [];
+        $data['category'] = 'order';
+        $data['order_id'] = $order['id'];
+        $data['invoice_id'] = $invoice_id;
+        $data['add_time'] = time();
+        $data['is_pay'] = $order['paid'] == 1 ? 1 : 0;
+        $data = array_merge($data, $invoice);
+        if (!$re = $this->dao->save($data)) {
+            throw new AdminException(410251);
+        }
+        if (sys_config('elec_invoice', 1) == 1 && sys_config('auto_invoice', 1) == 1 && $data['is_pay'] == 1) {
+            //自动开票
+            OrderInvoiceJob::dispatchSecs(10, 'autoInvoice', [$re->id]);
+        }
+
+        //自定义事件-申请开票
+        event('CustomEventListener', ['order_invoice', [
+            'uid' => $uid,
+            'order_id' => $order_id,
+            'phone' => $order['user_phone'],
+            'invoice_id' => $re->id,
+            'add_time' => date('Y-m-d H:i:s'),
+        ]]);
+
+        return ['id' => $re->id];
+    }
+
+    public function setInvoice(int $id, array $data)
+    {
+        $orderInvoice = $this->dao->get($id);
+        if (!$orderInvoice) {
+            throw new AdminException(100026);
+        }
+        if ($data['is_invoice'] == 1) {
+            $data['invoice_time'] = time();
+        }
+        if (!$this->dao->update($id, $data, 'id')) {
+            throw new AdminException(100015);
+        }
+        return true;
+    }
+
+    /**
+     * 拆分订单同步拆分申请开票记录
+     * @param int $oid
+     * @return bool
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     */
+    public function splitOrderInvoice(int $oid)
+    {
+        /** @var StoreOrderServices $storeOrderServices */
+        $storeOrderServices = app()->make(StoreOrderServices::class);
+        $orderInfo = $storeOrderServices->getOne(['id' => $oid, 'is_del' => 0]);
+        if (!$orderInfo) {
+            throw new AdminException(410173);
+        }
+        $pid = $orderInfo['pid'] > 0 ? $orderInfo['pid'] : $orderInfo['id'];
+        //查询开票记录
+        $orderInvoice = $this->dao->get(['order_id' => $oid]);
+        //查询子订单
+        $spliteOrder = $storeOrderServices->getColumn(['pid' => $pid, 'is_system_del' => 0], 'id,order_id');
+        if ($spliteOrder && $orderInvoice) {
+            $data = $orderInvoice->toArray();
+            unset($data['id']);
+            $data['add_time'] = strtotime($data['add_time']);
+            $data_all = [];
+            foreach ($spliteOrder as $order) {
+                if (!$this->dao->count(['order_id' => $order['id']])) {
+                    $data['order_id'] = $order['id'];
+                    $data_all[] = $data;
+                }
+            }
+            if ($data_all) {
+                $this->transaction(function () use ($data_all, $orderInvoice, $orderInfo) {
+                    $this->dao->saveAll($data_all);
+                    if ($orderInfo['pid'] <= 0) {
+                        $this->dao->update(['id' => $orderInvoice['id']], ['is_del' => 1]);
+                    }
+                });
+            }
+        }
+        return true;
+    }
+
+    /**
+     * 开具发票
+     * @param $id
+     * @return bool
+     * @throws \ReflectionException
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/5/15
+     */
+    public function invoiceIssuance($id)
+    {
+        if (sys_config('elec_invoice', 1) != 1) {
+            return app('json')->fail('电子发票功能未开启,请在一号通中开启并且在商城后台一号通配置中开启');
+        }
+        $info = $this->dao->getOne(['id' => $id]);
+        $orderInfo = app()->make(StoreOrderServices::class)->get($info['order_id']);
+        $cartInfo = app()->make(StoreOrderCartInfoServices::class)->getOrderCartInfo($orderInfo['id']);
+        $data = [];
+        $data['is_tax_inclusive'] = 1;
+        $data['account_name'] = $info['name'];
+        $data['bank_name'] = '';
+        $data['bank_account'] = '';
+        $data['telephone'] = $info['drawer_phone'];
+        $data['company_address'] = '';
+        $data['drawer'] = '';
+        $data['amount'] = $orderInfo['pay_price'];
+        if ($info['header_type'] == 1) {
+            $data['invoice_type'] = 82;
+            $data['tax_id'] = '';
+            $data['is_enterprise'] = 0;
+        } else {
+            $data['invoice_type'] = 81;
+            $data['tax_id'] = $info['duty_number'];
+            $data['is_enterprise'] = 1;
+        }
+        $goods = [];
+        foreach ($cartInfo as $item) {
+            $goods[] = [
+                'cate_id' => sys_config('elec_invoice_cate', 1799),
+                'store_name' => $item['cart_info']['productInfo']['store_name'],
+                'unit_price' => bcadd($item['cart_info']['sum_price'], $item['cart_info']['postage_price'], 2),
+                'num' => $item['cart_info']['cart_num'],
+                'tax_rate' => sys_config('elec_invoice_tax_rate', 13),
+            ];
+        }
+        $data['goods'] = $goods;
+        try {
+            $invoice = app()->make(ServeServices::class)->invoice();
+            $res = $invoice->invoiceIssuance($orderInfo['order_id'], $data);
+            if ($res['status'] == 200) {
+                $this->dao->update($id, [
+                    'is_invoice' => 1,
+                    'unique_num' => $orderInfo['order_id'],
+                    'invoice_num' => $res['data']['invoice_num'],
+                    'invoice_type' => $res['data']['invoice_type'],
+                    'invoice_serial_number' => $res['data']['invoice_serial_number'],
+                    'invoice_time' => time()
+                ]);
+            }
+        } catch (\Exception $e) {
+            Log::error('自动开具发票失败,失败原因:' . $e->getMessage());
+        }
+        return true;
+    }
+
+    /**
+     * 未开发票自动开具电子发票
+     * @return bool
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/5/15
+     */
+    public function autoInvoice()
+    {
+        if (sys_config('elec_invoice', 1) != 1) {
+            return true;
+        }
+        if (sys_config('auto_invoice', 1) == 1) {
+            $list = $this->dao->getColumn([
+                ['is_pay', '=', 1],
+                ['is_invoice', '=', 1],
+                ['unique_num', '=', ''],
+                ['is_del', '=', 0],
+                ['add_time', '<', time() - 60],
+            ], 'id');
+            if ($list) {
+                foreach ($list as $item) {
+                    //自动开票
+                    OrderInvoiceJob::dispatchSecs(10, 'autoInvoice', [$item]);
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
+     * 退款订单自动冲红
+     * @return bool
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/5/15
+     */
+    public function autoInvoiceRed()
+    {
+        if (sys_config('elec_invoice', 1) != 1) {
+            return true;
+        }
+        if (sys_config('auto_invoice', 1) == 1) {
+            $list = $this->dao->getColumn([
+                ['is_pay', '=', 1],
+                ['is_invoice', '=', 1],
+                ['unique_num', '<>', ''],
+                ['red_invoice_num', '=', ''],
+                ['is_del', '=', 1],
+                ['add_time', '<', time() - 60],
+            ], 'id');
+            if ($list) {
+                foreach ($list as $item) {
+                    //自动冲红
+                    OrderInvoiceJob::dispatchSecs(10, 'autoInvoiceRed', [$item]);
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
+     * 负数发票开具
+     * @param $id
+     * @return bool
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @author wuhaotian
+     * @email 442384644@qq.com
+     * @date 2024/5/16
+     */
+    public function redInvoiceIssuance($id)
+    {
+        $invoiceInfo = $this->dao->get($id);
+        if ($invoiceInfo['is_pay'] == 0 || $invoiceInfo['is_invoice'] == 0 || $invoiceInfo['unique_num'] == '') {
+            throw new AdminException('发票状态有误,请检查');
+        }
+        $invoice = app()->make(ServeServices::class)->invoice();
+        $redInfo = $invoice->applyRedInvoice(['invoice_num' => $invoiceInfo['invoice_num'], 'apply_type' => '01']);
+        if ($redInfo['status'] != 200) throw new AdminException('申请红字发票失败,请检查');
+        $res = $invoice->redInvoiceIssuance(['invoice_num' => $invoiceInfo['invoice_num'], 'red_number' => $redInfo['data']['red_number']]);
+        if ($res['status'] != 200) throw new AdminException('开具负数发票失败,请检查');
+        $this->dao->update($id, ['red_invoice_num' => $redInfo['data']['red_number']]);
+        return true;
+    }
+}

+ 39 - 2
crmeb/app/services/order/StoreOrderRefundServices.php

@@ -285,6 +285,21 @@ class StoreOrderRefundServices extends BaseServices
         $order['phone'] = $order['user_phone'];
         event('CustomNoticeListener', [$order['uid'], $order, 'order_refund_success']);
 
+        //自定义事件-后台订单退款
+        event('CustomEventListener', ['admin_order_refund_success', [
+            'uid' => $order['uid'],
+            'order_id' => $order['order_id'],
+            'real_name' => $order['real_name'],
+            'user_phone' => $order['user_phone'],
+            'user_address' => $order['user_address'],
+            'total_num' => $order['total_num'],
+            'pay_price' => $order['pay_price'],
+            'refund_reason_wap' => $order['refund_reason_wap'],
+            'refund_reason_wap_explain' => $order['refund_reason_wap_explain'],
+            'refund_price' => $order['refund_price'],
+            'refund_time' => date('Y-m-d H:i:s'),
+        ]]);
+
         return true;
     }
 
@@ -717,6 +732,18 @@ class StoreOrderRefundServices extends BaseServices
         //自定义消息-退款失败
         event('CustomNoticeListener', [$orderRefundInfo['uid'], $orderRefundInfo->toArray(), 'order_refund_fail']);
 
+        //自定义事件-后台订单拒绝退款
+        event('CustomEventListener', ['admin_order_refund_fail', [
+            'uid' => $orderRefundInfo['uid'],
+            'id' => $orderRefundInfo['id'],
+            'store_order_id' => $orderRefundInfo['store_order_id'],
+            'order_id' => $orderRefundInfo['order_id'],
+            'refund_num' => $orderRefundInfo['refund_num'],
+            'refund_price' => $orderRefundInfo['refund_price'],
+            'refuse_reason' => $orderRefundInfo['refuse_reason'],
+            'refuse_time' => date('Y-m-d H:i:s'),
+        ]]);
+
         return true;
     }
 
@@ -1041,8 +1068,18 @@ class StoreOrderRefundServices extends BaseServices
         //推送订单
         event('OutPushListener', ['refund_create_push', ['order_id' => (int)$order['id']]]);
 
-        //自定义消息-订单发起退款
-//        event('CustomNoticeListener', [$order['uid'], $order->toArray(), 'order_initiated_refund']);
+        //自定义事件-订单申请退款
+        event('CustomEventListener', ['order_initiated_refund', [
+            'uid' => $uid,
+            'refund_order_id' => $refundData['order_id'],
+            'order_id' => $order['order_id'],
+            'real_name' => $order['real_name'],
+            'user_phone' => $order['user_phone'],
+            'user_address' => $order['user_address'],
+            'refund_num' => $refundData['refund_num'],
+            'refund_price' => $refundData['refund_price'],
+            'refund_time' => date('Y-m-d H:i:s', $refundData['add_time']),
+        ]]);
 
         try {
             ChannelService::instance()->send('NEW_REFUND_ORDER', ['order_id' => $order['order_id']]);

+ 27 - 1
crmeb/app/services/order/StoreOrderServices.php

@@ -789,7 +789,7 @@ HTML;
         $createServices = app()->make(StoreOrderCreateServices::class);
         $data['order_id'] = $createServices->getNewOrderId('cp');
         if (sys_config('user_brokerage_type') == 1) {
-            $percent = bcdiv((string)$data['pay_price'], (string)$order['pay_price'], 6);
+            $percent = $order['pay_price'] != 0 ? bcdiv((string)$data['pay_price'], (string)$order['pay_price'], 6) : $order['pay_price'];
             if ($order['one_brokerage'] > 0) {
                 $data['one_brokerage'] = bcmul((string)$order['one_brokerage'], $percent, 2);
             }
@@ -822,6 +822,16 @@ HTML;
                 //自定义消息-订单改价
                 $order['change_price'] = $data['pay_price'];
                 event('NoticeListener', [$order['uid'], $order, 'price_change_price']);
+
+                //自定义事件-订单改价
+                event('CustomEventListener', ['admin_order_change', [
+                    'uid' => $order['uid'],
+                    'order_id' => $data['order_id'],
+                    'pay_price' => $data['pay_price'],
+                    'gain_integral' => $data['gain_integral'],
+                    'change_time' => date('Y-m-d H:i:s'),
+                ]]);
+
                 return $data['order_id'];
             } else {
                 throw new AdminException(100007);
@@ -1913,6 +1923,22 @@ HTML;
                 throw new ApiException(100020);
             }
         });
+
+        //自定义事件-订单取消
+        event('CustomEventListener', ['order_cancel', [
+            'uid' => $uid,
+            'id' => $order['id'],
+            'order_id' => $order_id,
+            'real_name' => $order['id'],
+            'user_phone' => $order['id'],
+            'user_address' => $order['id'],
+            'total_num' => $order['id'],
+            'pay_price' => $order['id'],
+            'deduction_price' => $order['id'],
+            'coupon_price' => $order['id'],
+            'cancel_time' => date('Y-m-d H:i:s'),
+        ]]);
+
         return true;
     }
 

+ 17 - 4
crmeb/app/services/order/StoreOrderSuccessServices.php

@@ -106,10 +106,23 @@ class StoreOrderSuccessServices extends BaseServices
         $orderInfo['phone'] = $orderInfo['user_phone'];
         event('CustomNoticeListener', [$orderInfo['uid'], $orderInfo, 'order_pay_success']);
 
-        // 小程序订单管理 (自提商品)
-        if ($orderInfo['shipping_type'] == 2) {
-            event('OrderShipping', ['product', $orderInfo, 4, '', '']);
-        }
+        //自定义事件-订单支付
+        event('CustomEventListener', ['order_pay', [
+            'uid' => $orderInfo['uid'],
+            'id' => (int)$orderInfo['id'],
+            'order_id' => $orderInfo['order_id'],
+            'real_name' => $orderInfo['real_name'],
+            'user_phone' => $orderInfo['user_phone'],
+            'user_address' => $orderInfo['user_address'],
+            'total_num' => $orderInfo['total_num'],
+            'pay_price' => $orderInfo['pay_price'],
+            'pay_postage' => $orderInfo['pay_postage'],
+            'deduction_price' => $orderInfo['deduction_price'],
+            'coupon_price' => $orderInfo['coupon_price'],
+            'store_name' => $orderInfo['storeName'],
+            'add_time' => date('Y-m-d H:i:s', $orderInfo['add_time']),
+        ]]);
+
         $res = $res1 && $resPink;
         return false !== $res;
     }

+ 44 - 2
crmeb/app/services/order/StoreOrderTakeServices.php

@@ -149,6 +149,25 @@ class StoreOrderTakeServices extends BaseServices
                 $order['time'] = date('Y-m-d H:i:s');
                 $order['phone'] = $order['user_phone'];
                 event('CustomNoticeListener', [$order['uid'], $order, 'order_take']);
+
+                //自定义事件-订单收货/核销
+                event('CustomEventListener', ['order_take', [
+                    'uid' => $order['uid'],
+                    'id' => (int)$order['id'],
+                    'order_id' => $order['order_id'],
+                    'real_name' => $order['real_name'],
+                    'user_phone' => $order['user_phone'],
+                    'user_address' => $order['user_address'],
+                    'total_num' => $order['total_num'],
+                    'pay_price' => $order['pay_price'],
+                    'pay_postage' => $order['pay_postage'],
+                    'deduction_price' => $order['deduction_price'],
+                    'coupon_price' => $order['coupon_price'],
+                    'store_name' => $storeTitle,
+                    'add_time' => date('Y-m-d H:i:s', $order['add_time']),
+                ]]);
+
+
             } catch (\Throwable $exception) {
 
             }
@@ -225,13 +244,24 @@ class StoreOrderTakeServices extends BaseServices
             //自定义消息-积分到账
             event('CustomNoticeListener', [$order['uid'], [
                 'uid' => $order['uid'],
-                'phone' => app()->make(UserServices::class)->value($order['uid'], 'phone'),
+                'phone' => $userInfo['phone'],
                 'storeTitle' => $storeTitle,
                 'give_integral' => $give_integral,
                 'integral' => $integral,
                 'time' => date('Y-m-d H:i:s'),
             ], 'point_received']);
 
+            //自定义事件-积分到账
+            event('CustomEventListener', ['order_point', [
+                'uid' => $order['uid'],
+                'order_id' => $order['order_id'],
+                'phone' => $userInfo['phone'],
+                'storeTitle' => $storeTitle,
+                'give_integral' => $give_integral,
+                'integral' => $integral,
+                'add_time' => date('Y-m-d H:i:s'),
+            ]]);
+
             return true;
         }
         return true;
@@ -527,16 +557,28 @@ class StoreOrderTakeServices extends BaseServices
         //提醒推送
         event('NoticeListener', [['spread_uid' => $spread_uid, 'userType' => $userType, 'brokeragePrice' => $brokeragePrice, 'goodsName' => $goodsName, 'goodsPrice' => $goodsPrice, 'add_time' => $orderInfo['add_time'] ?? time()], 'order_brokerage']);
 
+        $spreadPhone = app()->make(UserServices::class)->value($spread_uid, 'phone');
+
         //自定义消息-佣金到账
         event('CustomNoticeListener', [$spread_uid, [
             'uid' => $spread_uid,
-            'phone' => app()->make(UserServices::class)->value($spread_uid, 'phone'),
+            'phone' => $spreadPhone,
             'brokeragePrice' => $brokeragePrice,
             'goodsName' => $goodsName,
             'goodsPrice' => $goodsPrice,
             'time' => date('Y-m-d H:i:s')
         ], 'brokerage_received']);
 
+        //自定义事件-佣金到账
+        event('CustomEventListener', ['order_brokerage', [
+            'uid' => $spread_uid,
+            'order_id' => $orderInfo['order_id'],
+            'phone' => $spreadPhone,
+            'brokeragePrice' => $brokeragePrice,
+            'goodsName' => $goodsName,
+            'goodsPrice' => $goodsPrice,
+            'add_time' => date('Y-m-d H:i:s')
+        ]]);
     }
 
 

+ 1 - 2
crmeb/app/services/order/StoreOrderWriteOffServices.php

@@ -130,9 +130,8 @@ class StoreOrderWriteOffServices extends BaseServices
             if (!$re) {
                 throw new ApiException(410272);
             }
-            // 小程序订单管理
             if ($orderInfo['shipping_type'] == 2) {
-                event('OrderShipping', ['product', $orderInfo, 1, '123456', '中通快递']);
+                event('OrderShippingListener', ['product', $orderInfo, 4, '', '']);
             }
             return $orderInfo->toArray();
         } else {

+ 8 - 0
crmeb/app/services/product/product/StoreProductRelationServices.php

@@ -118,6 +118,14 @@ class StoreProductRelationServices extends BaseServices
         }
         //收藏记录
         ProductLogJob::dispatch(['collect', ['uid' => $uid, 'product_id' => $productId]]);
+
+        //自定义事件-用户商品收藏
+        event('CustomEventListener', ['user_product_collect', [
+            'product_id' => $productId,
+            'uid' => $uid,
+            'collect_time' => date('Y-m-d H:i:s'),
+        ]]);
+
         return true;
     }
 

+ 1 - 0
crmeb/app/services/product/product/StoreProductReplyServices.php

@@ -90,6 +90,7 @@ class StoreProductReplyServices extends BaseServices
         $data['reply_type'] = 'product';
         $data['add_time'] = empty($data['add_time']) ? $time : strtotime($data['add_time']);
         $data['pics'] = json_encode($data['pics']);
+        $data['status'] = 1;
         unset($data['image']);
         if ($data['add_time'] > $time) {
             throw new AdminException(400567);

+ 0 - 0
crmeb/app/services/product/product/StoreProductServices.php


Некоторые файлы не были показаны из-за большого количества измененных файлов