| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468 |
- <?php
- /**
- * 厦门云联储网络科技有限公司
- * https://www.baokuaiyun.com
- * Copyright (c) 2023 爆块云 All rights reserved.
- */
- namespace app\models;
- use yii\db\Query;
- use yii\db\Expression;
- use yii\helpers\Json;
- /**
- * This is the model class for table "{{%order_fack}}".
- *
- * @property integer $id
- * @property integer $store_id
- * @property integer $user_id
- * @property string $order_no
- * @property string $total_price
- * @property string $pay_price
- * @property string $name
- * @property string $mobile
- * @property string $address
- * @property string $address_data
- * @property integer $is_pay
- * @property integer $pay_type
- * @property integer $pay_time
- * @property integer $send_time
- * @property integer $confirm_time
- * @property integer $is_comment
- * @property integer $created_at
- * @property integer $is_delete
- * @property integer $goods_id
- * @property string $goods_name
- * @property string $virtual_user
- * @property integer $is_virtual
- * @property integer $trade_status
- * @property integer $mch_id
- * @property integer $updated_at
- */
- class OrderFack extends \yii\db\ActiveRecord
- {
- // 从 Order.php 复制常量定义
- /**
- * 订单流转状态:默认
- */
- const ORDER_FLOW_DEFAULT = -1;
- /**
- * 订单流转状态:待发货
- */
- const ORDER_FLOW_NO_SEND = 0;
- /**
- * 订单流转状态:已取消
- */
- const ORDER_FLOW_CANCEL = 1;
- /**
- * 订单流转状态:已发货
- */
- const ORDER_FLOW_SEND = 2;
- /**
- * 订单流转状态:已完成
- */
- const ORDER_FLOW_CONFIRM = 3;
- const TRADE_STATUS_TEXT = [
- self::ORDER_FLOW_DEFAULT => '待付款',
- self::ORDER_FLOW_NO_SEND => '待发货',
- self::ORDER_FLOW_SEND => '已发货',
- self::ORDER_FLOW_CANCEL => '已取消',
- self::ORDER_FLOW_CONFIRM => '已完成',
- ];
- /**
- * 是否支付:已支付
- */
- const IS_PAY_TRUE = 1;
- /**
- * 是否支付:未支付
- */
- const IS_PAY_FALSE = 0;
- /**
- * 支付方式:微信支付
- */
- const PAY_TYPE_WECHAT = 1;
- /**
- * 支付方式:支付宝支付
- */
- const PAY_TYPE_ALI = 4;
- /**
- * 是否取消(手动):已取消
- */
- const IS_DELETE_TRUE = 1;
- /**
- * 是否取消(手动):未取消
- */
- const IS_DELETE_FALSE = 0;
- /**
- * @inheritdoc
- */
- public static function tableName()
- {
- return '{{%order_fack}}';
- }
- /**
- * @inheritdoc
- */
- public function rules()
- {
- return [
- [['store_id', 'user_id', 'order_no', 'total_price', 'pay_price'], 'required'],
- [['store_id', 'user_id', 'is_pay', 'pay_type', 'pay_time', 'send_time', 'confirm_time',
- 'is_comment', 'created_at', 'is_delete', 'goods_id', 'is_virtual', 'trade_status', 'mch_id', 'updated_at'], 'integer'],
- [['total_price', 'pay_price'], 'number'],
- [['order_no', 'name', 'mobile', 'goods_name', 'virtual_user'], 'string', 'max' => 255],
- [['address'], 'string', 'max' => 1000],
- [['address_data'], 'string'],
- ];
- }
- /**
- * @inheritdoc
- */
- public function attributeLabels()
- {
- return [
- ];
- }
- /**
- * 生成虚拟订单
- */
- public static function generateVirtualOrders($goodsId, $storeId, $count = null)
- {
- if ($count === null) {
- $count = rand(5, 15); // 随机5-15条虚拟订单
- }
- $orders = [];
- $currentTime = time();
- for ($i = 0; $i < $count; $i++) {
- $address = self::getAddress();
- // 根据订单位置设置不同的时间范围
- if ($i > 20) {
- // 前10条订单:最近30分钟内
- $orderTime = $currentTime - rand(0, 1800); // 0-30分钟
- } else {
- // 其他订单:24小时内(30分钟-24小时)
- $orderTime = $currentTime - rand(1800, 86400); // 30分钟-24小时
- }
- // 根据订单时间计算后续时间点(保持合理的时间间隔)
- $payTime = $orderTime + rand(60, 1800); // 1-30分钟内支付(快速支付)
- $sendTime = $payTime + rand(3600, 21600); // 1-6小时内发货(快速发货)
- $confirmTime = $sendTime + rand(86400, 172800); // 1-2天内确认收货
- $order = new self();
- $order->store_id = 1;
- $order->user_id = $address->user_id;
- $order->order_no = 'VF' . date('YmdHis', $orderTime) . rand(1000, 9999); // 使用订单时间生成订单号
- $order->total_price = rand(100, 500) + rand(0, 99) / 100;
- $order->pay_price = $order->total_price;
- $order->name = $address->name;
- $order->mobile = $address->mobile;
- $order->address = trim($address->province).trim($address->city).trim($address->district).trim($address->detail);
- $order->is_pay = 1;
- $order->pay_type = 1;
- $order->pay_time = $payTime;
- $order->send_time = $sendTime;
- $order->confirm_time = $confirmTime;
- $order->is_comment = rand(0, 1); // 随机是否已评价
- $order->created_at = $orderTime;
- $order->is_delete = 0;
- $order->goods_id = $goodsId;
- $order->goods_name = '虚拟商品';
- $order->virtual_user = '';
- $order->is_virtual = 1;
- $order->trade_status = 3; // 已确认收货
- $order->mch_id = 0;
- $order->updated_at = $currentTime;
- $order->address_data = json_encode([
- 'province' => trim($address->province),
- 'city' => trim($address->city),
- 'district' => trim($address->district),
- 'detail' => trim($address->detail),
- 'latitude' => $address->latitude,
- 'longitude' => $address->longitude,
- ], JSON_UNESCAPED_UNICODE);
- $orders[] = $order;
- }
- return $orders;
- }
- private static function getAddress()
- {
- for ($i = 0; $i < 10; $i++){
- $address = Address::find()->where(['is_delete' => 0])->orderBy('RAND()')->one();
- $fack = OrderFack::find()->where(['user_id'=>$address->user_id])->one();
- if(!$fack){
- return $address;
- }
- }
- return $address;
- }
- /**
- * 获取商品的虚拟订单
- */
- public static function getGoodsVirtualOrders($goodsId, $storeId)
- {
- try {// 先查询已存在的虚拟订单
- $fiveMinutesAgo = time() - 300; // 当前时间戳 - 300秒(5分钟)
- $existingOrders = self::find()
- ->where(['goods_id' => $goodsId, 'is_delete' => 0])
- ->andWhere(['>=', 'created_at', $fiveMinutesAgo])
- ->orderBy(['created_at' => SORT_DESC])
- ->all();// 如果没有数据,生成新的虚拟订单
- if (empty($existingOrders)) {
- // 生成随机数量(20-100条)
- $randomCount = rand(1, 3);
- $newOrders = self::generateVirtualOrders($goodsId, $storeId, $randomCount);
- $successCount = 0;
- foreach ($newOrders as $index => $order) {
- // 设置创建时间:前10条在0-30分钟内,其余在24小时内随机分布
- /*if ($index < 10) {
- // 0-30分钟内的随机时间
- $minutes = rand(0, 30);
- } else {
- // 其他订单在24小时内随机分布
- $minutes = rand(30, 24 * 60 - 1); // 30-1439分钟(确保在24小时内但超过30分钟)
- }
- $order->created_at = date('Y-m-d H:i:s', strtotime("-$minutes minutes"));*/
- if (!$order->save()) {
- throw new \Exception('保存虚拟订单失败:' . json_encode($order->getErrorSummary(false)[0]));
- // 同时生成订单详情
- //OrderDetailFack::generateVirtualOrderDetail($order);
- }
- $successCount++;
- }
- return true;
- }// 如果有数据,检查最新10条数据的时间分布
- $recentOrders = array_slice($existingOrders, 0, 10);
- $currentTime = time();
- $thirtyMinutesAgo = $currentTime - (30 * 60);
- $needsTimeAdjustment = false;// 检查前10条订单是否都在30分钟内
- foreach ($recentOrders as $order) {
- $orderTime = strtotime($order->created_at);
- if ($orderTime < $thirtyMinutesAgo) {
- $needsTimeAdjustment = true;
- break;
- }
- }// 如果需要调整时间,更新前10条订单的时间
- if ($needsTimeAdjustment) {
- self::adjustRecentOrdersTime($goodsId, 10);
- }
- return true;
- } catch (\Exception $e) {
- ActionLog::addLog(1,'OrderFackJob',$e->getMessage());
- }catch (\Throwable $e) {
- ActionLog::addLog(1,'OrderFackJob',$e->getMessage());
- }
- }
- private static function adjustRecentOrdersTime($goodsId, $count)
- {
- // 获取需要调整的订单(按创建时间倒序,取最新的几个)
- $ordersToAdjust = self::find()
- ->where(['goods_id' => $goodsId, 'is_delete' => 0])
- ->orderBy(['created_at' => SORT_DESC])
- ->limit($count)
- ->all();
- foreach ($ordersToAdjust as $index => $order) {
- // 修改为0-30分钟内的随机时间
- $minutes = rand(0, 30);
- $order->created_at = date('Y-m-d H:i:s', strtotime("-$minutes minutes"));
- $order->save();
- }
- }
- /**
- * 获取混合订单(真实+虚拟)
- */
- public static function getMixedOrders($goodsId, $limit = 20, $page = 1)
- {
- // 构建联合查询
- $query = new Query();
- $offset = ($page - 1) * $limit;
- // 真实订单查询 - 添加 avatar_url
- $realQuery = (new Query())
- ->select([
- 'o.id', 'o.user_id', 'o.name','o.address_data', 'o.created_at',
- 'u.avatar_url',
- //new \yii\db\Expression("'real' as order_type")
- ])
- ->from(['o' => Order::tableName()])
- ->innerJoin(['od' => OrderDetail::tableName()], 'o.id = od.order_id')
- ->leftJoin(['u' => User::tableName()], 'o.user_id = u.id') // 左连接用户表
- ->where([
- 'od.goods_id' => $goodsId,
- 'o.is_delete' => 0
- ]);
- // 虚拟订单查询 - 添加 avatar_url
- $virtualQuery = (new Query())
- ->select([
- 'of.id', 'of.user_id', 'of.name','of.address_data', 'of.created_at',
- 'u.avatar_url',
- //new \yii\db\Expression("'virtual' as order_type")
- ])
- ->from(['of' => OrderFack::tableName()])
- ->leftJoin(['u' => User::tableName()], 'of.user_id = u.id') // 左连接用户表
- ->where([
- //'of.goods_id' => $goodsId,
- 'of.is_delete' => 0
- ]);
- // 合并查询
- $unionQuery = (new Query())
- ->from(['union_data' => $realQuery->union($virtualQuery, true)]);
- $countQuery = clone $unionQuery;
- // 先获取基础订单数据
- $baseOrders = $unionQuery
- ->orderBy('created_at DESC')
- ->offset($offset)
- ->limit($limit)
- ->all();
- if (empty($baseOrders)) {
- return [];
- }
- // 提取所有用户ID
- $userIds = array_unique(array_column($baseOrders, 'user_id'));
- // 分别查询真实订单和虚拟订单的用户购买次数
- $realPurchaseCounts = (new Query())
- ->select(['o.user_id', 'COUNT(*) as purchase_count'])
- ->from(['o' => Order::tableName()])
- ->innerJoin(['od' => OrderDetail::tableName()], 'o.id = od.order_id')
- ->where([
- 'od.goods_id' => $goodsId,
- 'o.is_delete' => 0,
- 'o.user_id' => $userIds
- ])
- ->groupBy('o.user_id')
- ->indexBy('user_id')
- ->all();
- $virtualPurchaseCounts = (new Query())
- ->select(['user_id', 'COUNT(*) as purchase_count'])
- ->from(OrderFack::tableName())
- ->where([
- //'goods_id' => $goodsId,
- 'is_delete' => 0,
- 'user_id' => $userIds
- ])
- ->groupBy('user_id')
- ->indexBy('user_id')
- ->all();
- // 合并购买次数(真实订单 + 虚拟订单)
- $purchaseCounts = [];
- foreach ($userIds as $userId) {
- $realCount = isset($realPurchaseCounts[$userId]) ? $realPurchaseCounts[$userId]['purchase_count'] : 0;
- $virtualCount = isset($virtualPurchaseCounts[$userId]) ? $virtualPurchaseCounts[$userId]['purchase_count'] : 0;
- $purchaseCounts[$userId] = $realCount + $virtualCount;
- }
- // 将购买次数添加到订单数据中
- foreach ($baseOrders as &$order) {
- $order['purchase_count'] = $purchaseCounts[$order['user_id']] ?? 0;
- $order['formatted_time'] = self::formatOrderTime($order['created_at']);
- $address = Json::decode($order['address_data']);
- if (!empty($address['city'])) $order['city'] = $address['city'];
- unset($order['address_data']);
- //处理数据将名字后面*处理
- $order['name'] = self::maskName($order['name']);
- }
- $data['list'] = $baseOrders;
- $data['pageNo'] = $page;
- $data['pageSize'] = $limit;
- $data['totalCount'] = $countQuery->count();
- return $data;
- }
- //对姓名进行脱敏处理
- private static function maskName($name) {
- if (empty($name)) {
- return '';
- }
-
- // 获取第一个字符
- $firstChar = mb_substr($name, 0, 1, 'UTF-8');
-
- // 获取姓名长度
- $length = mb_strlen($name, 'UTF-8');
-
- // 如果只有一个字,直接返回
- if ($length <= 1) {
- return $firstChar;
- }
-
- // 生成星号
- $stars = str_repeat('*', $length - 1);
-
- return $firstChar . $stars;
- }
- private static function formatOrderTime($orderTime)
- {
- if (empty($orderTime)) {
- return '';
- }
- $orderTimestamp = is_numeric($orderTime) ? $orderTime : strtotime($orderTime);
- $currentTimestamp = time();
- $diff = $currentTimestamp - $orderTimestamp;
- // 1分钟内显示"刚刚"
- if ($diff < 60) {
- return '刚刚';
- }
- // 1-10分钟内显示"一分钟前"
- if ($diff < 600) { // 10分钟 = 600秒
- return '一分钟前';
- }
- // 10-30分钟内显示"10分钟前"
- if ($diff < 1800) { // 30分钟 = 1800秒
- return '10分钟前';
- }
- // 检查是否是当天
- $orderDate = date('Y-m-d', $orderTimestamp);
- $currentDate = date('Y-m-d', $currentTimestamp);
- // 30分钟-当天23:59:59显示"半小时前"
- if ($orderDate === $currentDate) {
- return '半小时前';
- }
- // 不是当天则显示MM-DD
- return date('m-d', $orderTimestamp);
- }
- }
|