Parcourir la source

Merge branch 'master' of qk:yulf/general_channel

zhoulj il y a 4 ans
Parent
commit
0942f0c650

+ 4 - 2
README.md

@@ -5,5 +5,7 @@
 1.App\Consts\ 对应项目要有自身的配置;
 2.App\Controllers\ 控制器要有继承 重写或扩写自身项目的逻辑;
 3.App\Service\ 对应项目要继承相应的类 扩写自身项目的逻辑;
-4.composer 包安装 composer require genneral/channel @dev -vvv 
-4.composer 包更新 composer update genneral/channel -vvv 
+4.composer require genneral/channel=@dev 一般直接用这个,如果有稳定的包版本可以往下走
+5.项目代码更新需要标记版本 https://git-scm.com/book/zh/v2/Git-%E5%9F%BA%E7%A1%80-%E6%89%93%E6%A0%87%E7%AD%BE git 版本控制; 
+6.更新包管理平台 服务器上执行/usr/local/php/bin/php /usr/local/satis/bin/satis build /usr/local/satis/satis.json /usr/local/satis/repo 更新包的最新信息; https://comstock.zhuishuyun.com/ 查看有无对应包
+7.composer 包安装 composer require genneral/channel {包版本号} -vvv ;.composer 包更新 composer update genneral/channel {包版本号} -vvv 

+ 46 - 82
src/Controllers/BaseControllerConfig.php

@@ -5,10 +5,13 @@ namespace General\Controllers;
 use General\Models\Channel\Channel;
 use General\Models\Channel\ChannelUser;
 use General\Models\Channel\ChannelUsersInner;
+use Illuminate\Database\Eloquent\Model;
 
 /**
  * @property int $channel_id 站点ID
  * @property string $phone 登录手机号
+ * @property array $inner_phones 登录手机号
+ * @property ChannelUser $channel_user 分销后台账号
  * @property int $channel_user_id 分销后台账号ID
  * @property string $channel_name 分销渠道名称
  * @property string $channel_domain 分销渠道域名
@@ -16,133 +19,94 @@ use General\Models\Channel\ChannelUsersInner;
  * @property array $company_channel_ids 公司属下所有渠道ID
  * @property array $user_channel_ids 账号属下所有渠道ID
  * @property bool $is_inner 是否为内部站点
+ * @property int $sj_status 审计状态
+ * @property bool $is_sj_inner 是否为审计内部站点
  */
 trait BaseControllerConfig
 {
-    protected $field = [];
-
+    private $field = [];
     public function __get($name)
     {
         if (!isset($this->field[$name])) {
-            switch ($name) {
-                case 'channel_id':
-                    $this->field[$name] = (int)$this->getChannelId();
-                    break;
-                case 'channel_user_id':
-                    $this->field[$name] = (int)$this->getChannelUserId();
-                    break;
-                case 'channel_name':
-                    $this->field[$name] = $this->getChannelName();
-                    break;
-                case 'channel_domain':
-                    $this->field[$name] = $this->getChannelDomain();
-                    break;
-                case 'company_id':
-                    $this->field[$name] = (int)$this->getCompanyId();
-                    break;
-                case 'company_channel_ids':
-                    $this->field[$name] = $this->getALLChannelIDByCompanyID();
-                    break;
-                case 'user_channel_ids':
-                    $this->field[$name] = $this->getAllChannelIdByChannelUserId();
-                    break;
-                case 'is_inner':
-                    $this->field[$name] = $this->isInnerRole();
-                    break;
-                case 'phone':
-                    $this->field[$name] = $this->getLogPhone();
-                    break;
-                default:
-                    $this->field[$name] = $this->$name();
-                    break;
-            }
+            $this->field[$name] = $this->$name();
         }
         return $this->field[$name];
     }
 
-    function getShenjiStatus()
+    protected function channel(): Model
+    {
+        if (empty(session('ydychannel'))) {
+            if (env('APP_ENV') == 'local') return Channel::find(1);
+        }
+        return unserialize(session('ydychannel'));
+    }
+
+    protected function sj_status()
     {
         return redisEnv('SHENJI_SWITCH') ? 1 : 0;
     }
 
-    //获取分销渠道ID
-    function getChannelId()
+    protected function is_sj_inner(): bool
     {
-        if (empty(session('ydychannel'))) {
-            if (env('APP_ENV') == 'local') return 1;
-        }
-        $distribution_channel = unserialize(session('ydychannel'));
-        if ($distribution_channel) {
-            return $distribution_channel->id;
-        } else {
-            return 0;
-        }
+        return in_array($this->phone(), $this->getInnerPhone());
     }
 
-    //获取分销渠道名称
-    function getChannelName()
+    protected function inner_phones(): array
     {
-        if (empty(session('ydychannel'))) {
-            if (env('APP_ENV') == 'local') return '测试';
-        }
-        $distribution_channel = unserialize(session('ydychannel'));
-        return $distribution_channel->distribution_channel_name;
+        return ChannelUsersInner::where('is_enable', 1)->pluck('phone')->all();
     }
 
-    //获取分销渠道域名
-    function getChannelDomain()
+    protected function channel_id(): int
     {
-        if (empty(session('ydychannel'))) {
-            if (env('APP_ENV') == 'local') return 'site1.aizhuishu.com';
-        }
+        return $this->channel->id;
+    }
 
-        $distribution_channel = unserialize(session('ydychannel'));
-        return "site{$distribution_channel->id}.leyuee.com";
+    protected function channel_name(): string
+    {
+        return $this->channel->distribution_channel_name;
     }
 
-    //获取登陆用户ID
-    function getChannelUserId()
+    protected function channel_domain(): string
+    {
+        return "site{$this->channel_id}.leyuee.com";
+    }
+
+    protected function channel_user_id(): int
     {
         return session('ydyauth');
     }
 
-    //获取登陆号码
-    function getLogPhone()
+    protected function phone(): string
     {
         return session('ydylogphone');
     }
 
-    function getCompanyId()
+    protected function company_id(): int
     {
-        $channel_info = ChannelUser::find($this->channel_user_id);
-        if ($channel_info) {
-            return $channel_info->company_id ? $channel_info->company_id : 0;
-        }
-        return 0;
+        return $this->channel_user->id;
+    }
+
+    protected function channel_user(): ChannelUser
+    {
+        return ChannelUser::find($this->channel_user_id);
     }
 
-    function getALLChannelIDByCompanyID()
+    protected function company_channel_ids(): array
     {
-        return Channel::select('distribution_channels.id')
-            ->join('channel_users', 'channel_users.id', '=', 'distribution_channels.channel_user_id')
-            ->join('companies', 'companies.id', '=', 'channel_users.company_id')
-            ->where('companies.id', $this->company_id)
-            ->get()->pluck('id')
-            ->all();
+        $channel_user_ids = ChannelUser::where('company_id', $this->company_id)->pluck('id')->all();
+        return Channel::whereIn('channel_user_id', $channel_user_ids)->pluck('id')->all();
     }
 
-    //判断是否为内部站点
-    function isInnerRole()
+    protected function is_inner(): bool
     {
-        $lists = ChannelUsersInner::where('is_enable', 1)->get();
         $inner_phones = [];
-        foreach ($lists as $item) {
+        foreach ($this->inner_phones as $item) {
             $inner_phones[] = $item->phone . '2';
         }
         return in_array($this->phone, $inner_phones);
     }
 
-    public function getAllChannelIdByChannelUserId()
+    protected function user_channel_ids(): array
     {
         return Channel::where('channel_user_id', $this->channel_user_id)->get()->pluck('id')->all();
     }

+ 11 - 0
src/Controllers/Order/OrderController.php

@@ -0,0 +1,11 @@
+<?php
+
+namespace General\Controllers\Order;
+
+use General\Controllers\BaseControllerConfig;
+
+class OrderController
+{
+    use BaseControllerConfig;
+    
+}

+ 57 - 0
src/Helpers/AliOSSHelper.php

@@ -0,0 +1,57 @@
+<?php
+
+namespace General\Helpers;
+
+use Illuminate\Support\Facades\Log;
+use OSS\Core\OssException;
+use OSS\OssClient;
+
+class AliOSSHelper
+{
+
+    private $oss_client;
+
+    private $bucket;
+
+    public function __construct()
+    {
+        $this->oss_client = new OssClient(env('OSS_ACCESS_ID'), env('OSS_ACCESS_KEY'), env('OSS_END_POINT'));
+        $this->bucket = env('OSS_BUCKET', 'zhuishuyun');
+    }
+
+    public function uploadFile(string $oss_path, string $file_path, string $bucket = null)
+    {
+        $bucket = $bucket ? $bucket : $this->bucket;
+        try {
+            $oss_file = $this->oss_client->uploadFile($bucket, $oss_path, $file_path);
+            return $oss_file['oss-request-url'];
+        } catch (OssException $e) {
+            Log::error($e->getMessage());
+            return null;
+        }
+    }
+
+    public function uploadString(string $oss_path, string $content, string $bucket = null)
+    {
+        $bucket = $bucket ? $bucket : $this->bucket;
+        try {
+            $oss_file = $this->oss_client->putObject($bucket, $oss_path, $content);
+            return $oss_file['oss-request-url'];
+        } catch (OssException $e) {
+            Log::error($e->getMessage());
+            return null;
+        }
+    }
+
+    public function delFile(string $oss_path, string $bucket = null)
+    {
+        $bucket = $bucket ? $bucket : $this->bucket;
+        try {
+            $oss_file = $this->oss_client->deleteObject($bucket, $oss_path);
+            return $oss_file['oss-request-url'];
+        } catch (OssException $e) {
+            Log::error($e->getMessage());
+            return null;
+        }
+    }
+}

+ 115 - 0
src/Helpers/ExcelHelper.php

@@ -2,6 +2,9 @@
 
 namespace General\Helpers;
 
+use PhpOffice\PhpSpreadsheet\IOFactory;
+use PhpOffice\PhpSpreadsheet\Spreadsheet;
+
 /**
  * excel 工具类
  */
@@ -31,4 +34,116 @@ class ExcelHelper
         }
         exit();
     }
+
+    /**
+     * 导出csv到服务器
+     */
+    public static function saveFileCsv(array $column_names, array $data, string $file_name, string $path)
+    {
+        $file_path = $path . '/' . $file_name;
+        if (file_exists($file_path)) {
+            unlink($file_path);
+        }
+        $fp = fopen($file_path, "a");
+        $column_names = collect($column_names)->map(function ($item) {
+            return mb_convert_encoding($item, "GBK", "UTF-8");
+        })->all();
+        fputcsv($fp, $column_names);
+        $limit = 1000;
+        $calc = 0;
+        foreach ($data as $item) {
+            $calc++;
+            if ($limit == $calc) {
+                if (ob_get_level() > 0) {
+                    ob_flush();
+                }
+                flush();
+                $calc = 0;
+            }
+            $rows = collect($item)->map(function ($row) {
+                return mb_convert_encoding(is_numeric($row) && strlen($row) > 10 ? "'" . $row : $row, "GBK", "UTF-8");
+            })->all();
+            fputcsv($fp, $rows);
+        }
+        fclose($fp);
+    }
+
+
+    protected $excel_service;
+
+    public function __construct()
+    {
+        $this->excel_service = new Spreadsheet();
+    }
+
+    /**
+     * 保存Excel格式数据表 需要composer require phpoffice/phpspreadsheet
+     * @param string $title 
+     * @param array $header
+     * @param array $data
+     * @param string $file_name 
+     * @param string $path 
+     */
+    public function setExcelData(string $title, array $header, array $data, int $sheet_index = 0)
+    {
+        if ($sheet_index > 0) {
+            $this->excel_service->createSheet($sheet_index);
+        }
+        $this->excel_service->setActiveSheetIndex($sheet_index);
+        $sheet = $this->excel_service->getActiveSheet();
+        $sheet->setTitle($title);
+        $column_index = 1;
+        foreach ($header as $value) {
+            $sheet->getColumnDimensionByColumn($column_index)->setAutoSize(true);
+            $sheet->setCellValueByColumnAndRow($column_index, 1, $value);
+            $column_index++;
+        }
+        $row = 2;
+        foreach ($data as $val) {
+            $column_index = 1;
+            foreach ($val as $item) {
+                $sheet->setCellValueByColumnAndRow($column_index, $row, is_numeric($item) && strlen($item) > 10 ?  "'" . $item : $item);
+                $column_index++;
+            }
+            $row++;
+        }
+    }
+
+    public function saveExcelFile(string $file_name, string $path)
+    {
+        if (!$path) {
+            // Redirect output to a client’s web browser (Xlsx)
+            header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
+            header('Content-Disposition: attachment;filename=' . $file_name . ".xlsx");
+            header('Cache-Control: max-age=0');
+            // If you're serving to IE 9, then the following may be needed
+            header('Cache-Control: max-age=1');
+            // If you're serving to IE over SSL, then the following may be needed
+            header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past
+            header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); // always modified
+            header('Cache-Control: cache, must-revalidate'); // HTTP/1.1
+            header('Pragma: public'); // HTTP/1.0
+
+            $writer = IOFactory::createWriter($this->excel_service, 'Xlsx');
+            $writer->save('php://output');
+            //return true;
+        } else {
+            $writer = IOFactory::createWriter($this->excel_service, 'Xlsx');
+            $writer->save($path . '/' . $file_name);
+        }
+    }
+
+    public function saveExcelData(array $header, array $data, string $file_name, string $path)
+    {
+        $this->setExcelData(substr($file_name, 0, 30), $header, $data);
+        $this->saveExcelFile($file_name, $path);
+    }
+
+    public function saveExcelDataToMultiSheet(array $param, string $file_name, string $path = '')
+    {
+        foreach ($param as $item) {
+            $this->setExcelData($item['title'], $item['header'], $item['data']);
+        }
+        $this->saveExcelFile($file_name, $path);
+    }
 }

+ 49 - 0
src/Jobs/ExportTaskJob.php

@@ -0,0 +1,49 @@
+<?php
+
+namespace General\Jobs;
+
+use General\Helpers\ExcelHelper;
+use General\Services\Export\AbstractDataExportHandle;
+use General\Services\Export\AbstractExportTask;
+use Illuminate\Bus\Queueable;
+use Illuminate\Queue\SerializesModels;
+use Illuminate\Queue\InteractsWithQueue;
+use Illuminate\Contracts\Queue\ShouldQueue;
+use Illuminate\Foundation\Bus\Dispatchable;
+
+class ExportTaskJob implements ShouldQueue
+{
+    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
+
+    private $task;
+    private $export_handle;
+
+    /**
+     * Create a new job instance.
+     *
+     * @return void
+     */
+    public function __construct(AbstractExportTask $task, AbstractDataExportHandle $handle)
+    {
+        $this->task = $task;
+        $this->export_handle = $handle;
+    }
+
+    /**
+     * Execute the job.
+     *
+     * @return void
+     */
+    public function handle()
+    {
+        $task_model =  $this->task->getModel();
+        $this->task->setStatus(AbstractExportTask::running);
+        $data = $this->export_handle->getExportData();
+        $headers = $this->export_handle->getHeaders();
+        $file_name = md5($task_model->id . strtotime($task_model->created_at)) . ".csv";
+        $local_path = storage_path('tmp');
+        ExcelHelper::saveFileCsv($headers, $data, $file_name, $local_path);
+        $this->task->saveExportTaskFile($local_path, $file_name);
+        unlink($local_path . '/' . $file_name);
+    }
+}

+ 3 - 0
src/Models/Order/Order.php

@@ -4,6 +4,7 @@ namespace General\Models\Order;
 
 use General\Models\Report\ReportUserBindRecord;
 use General\Models\Report\ReportUserChargeRecord;
+use General\Models\TableSuffix;
 use General\Models\User\User;
 use Illuminate\Database\Eloquent\Model;
 
@@ -14,6 +15,8 @@ use Illuminate\Database\Eloquent\Model;
  */
 class Order extends Model
 {
+    use TableSuffix;
+
     protected $table = 'orders';
 
     protected $fillable = [

+ 36 - 0
src/Models/TableSuffix.php

@@ -0,0 +1,36 @@
+<?php
+
+namespace General\Models;
+
+use Illuminate\Support\Facades\DB;
+
+trait TableSuffix
+{
+    private static $suffix;
+
+    public static function suffix($suffix)
+    {
+        static::$suffix = $suffix;
+    }
+
+    public function __construct(array $attributes = [])
+    {
+        $this->table .= static::$suffix;
+        parent::__construct($attributes);
+    }
+
+    public static function model(string $suffix)
+    {
+        self::suffix($suffix);
+        $model = new self;
+        return $model;
+    }
+
+    public static function IndexRaw($index_raw)
+    {
+        $model = new static();
+        $name = "{$model->getTable()} use index ({$index_raw})";
+        $model->setTable(DB::raw($name));
+        return $model;
+    }
+}

+ 1 - 2
src/Requests/Request.php

@@ -17,8 +17,7 @@ abstract class Request extends FormRequest
     {
         throw (new HttpResponseException(response()->json([
             'code' => -1,
-            'msg' => '请求错误',
-            'data' => $validator->errors()->first(),
+            'msg' => $validator->errors()->first(),
         ], 200)));
     }
 

+ 69 - 0
src/Services/Export/AbstractDataExportHandle.php

@@ -0,0 +1,69 @@
+<?php
+
+namespace General\Services\Export;
+
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Support\Collection;
+
+/**
+ * 统计数据导出处理对象
+ */
+abstract class AbstractDataExportHandle
+{
+    private $query_params;
+    private $headers;
+
+    public function __construct(array $query_params, array $headers)
+    {
+        $this->query_params = $query_params;
+        $this->headers = $headers;
+    }
+
+    public function __call($name, $arguments)
+    {
+        $property_name = $name . 's';
+        $id = $arguments[0];
+        return array_key_exists($id, $this->$property_name) ? $this->$property_name[$id] : null;
+    }
+
+    /**
+     * 设置每行数据
+     */
+    abstract public function setItemData(Model $item): array;
+
+    /**
+     * 查询
+     */
+    abstract public function query(array $params): array;
+
+    /**
+     * Collection 对象转数组提高键值查询效率
+     */
+    protected function collectToArray(Collection $collections, string $key)
+    {
+        return $collections->keyBy($key)->all();
+    }
+
+    /**
+     * 获取导出数据
+     */
+    public function getExportData()
+    {
+        $result = [];
+        foreach ($this->query($this->query_params) as $item) {
+            $value = $this->setItemData($item);
+            if ($value) {
+                $result[] = $value;
+            }
+        }
+        return $result;
+    }
+
+    /**
+     * 导出excel的标题头
+     */
+    public function getHeaders()
+    {
+        return $this->headers;
+    }
+}

+ 88 - 0
src/Services/Export/AbstractExportTask.php

@@ -0,0 +1,88 @@
+<?php
+
+namespace General\Services\Export;
+
+use General\Helpers\AliOSSHelper;
+use Illuminate\Database\Eloquent\Model;
+
+/**
+ * 导出任务
+ * $model 对象必须有name,query_condition,status,file_path,is_file_deleted 逻辑不能变
+ */
+abstract class AbstractExportTask
+{
+    private $model;
+    private $query_data;
+
+    const ready = 1;
+    const running = 2;
+    const complete = 3;
+    const failure = 4;
+
+    public function __construct(Model $model, ExportQueryData $query_data = null)
+    {
+        $this->model = $model;
+        $this->query_data = $query_data;
+    }
+
+    abstract public function getTaskData(): array;
+
+    /**
+     * 创建导出任务
+     */
+    public function addTask(array $query_params)
+    {
+        if ($this->query_data) {
+            $params = array_merge($this->getTaskData(), [
+                'name' => $this->query_data->memu_name,
+                'query_condition' => $this->query_data->getQueryParamsContent($query_params),
+                'status' => self::ready,
+            ]);
+            $this->setModel($this->model::create($params));
+        }
+    }
+
+    public function setModel(Model $model)
+    {
+        $this->model = $model;
+    }
+
+    public function getModel(): Model
+    {
+        return $this->model;
+    }
+
+    /**
+     * 设置状态
+     */
+    public function setStatus(int $status)
+    {
+        $this->model->status = $status;
+        $this->model->save();
+    }
+
+    /**
+     * 保存文件
+     */
+    public function saveExportTaskFile(string $local_path, string $file_name)
+    {
+        $service = new AliOSSHelper;
+        $oss_path = $service->uploadFile("reports/" . $file_name, $local_path . '/' . $file_name);
+        if ($oss_path) {
+            $this->model->file_path = "reports/" . $file_name;
+            $this->setStatus(self::complete);
+        } else {
+            $this->task->setStatus(self::failure);
+        }
+    }
+    /**
+     * 删除文件
+     */
+    public function delExportTaskFile()
+    {
+        $service = new AliOSSHelper;
+        $service->delFile($this->model->file_path);
+        $this->model->is_file_deleted = 1;
+        $this->model->save();
+    }
+}

+ 28 - 0
src/Services/Export/ExportQueryData.php

@@ -0,0 +1,28 @@
+<?php
+
+namespace General\Services\Export;
+
+/**
+ * 导出查询类
+ */
+class ExportQueryData
+{
+    public $query_params_map;
+    public $memu_name;
+
+    public function __construct(array $query_params_map, string $memu_name)
+    {
+        $this->query_params_map = $query_params_map;
+        $this->memu_name = $memu_name;
+    }
+
+    public function getQueryParamsContent(array $params)
+    {
+        $content = "";
+        foreach ($params as $key => $value) {
+            $content .= isset($this->query_params_map[$key]) && $value !== '' ?
+                "{$this->query_params_map[$key]}: {$value};" : '';
+        }
+        return $content;
+    }
+}

+ 3 - 3
src/Services/LandingPage/ChargeFeedBack/QappRereport.php

@@ -11,7 +11,7 @@ use General\Services\Report\BaseReport;
 /**
  * qapp付费重传
  */
-class QappRereport
+class QappRereport extends Rereport
 {
     public function reportInstance(string $link_source): BaseReport
     {
@@ -21,11 +21,11 @@ class QappRereport
         return $instance;
     }
 
-    public function addReportCount(ReportUserBindRecord $report_user)
+    public function addReportCount(ReportUserBindRecord $report_user): array
     {
         $service = new Report;
         $user = User::find($report_user->uid);
-        $service->report('api/report/add', [
+        return $service->report('api/report/add', [
             'source' => BaseConst::Platform,
             'adid' => $report_user->adid,
             'channel_id' => $user->distribution_channel_id,

+ 1 - 0
src/Services/LandingPage/LandingPageLinkService.php

@@ -229,6 +229,7 @@ class LandingPageLinkService
     public function setReportType(int $channel_id, string $type, int $molecule, int $eligible_count)
     {
         if (in_array($type, LandingPageLinkService::REPORT_TYPE)) {
+            $molecule = $molecule == 0 ? 100 : $molecule;
             Redis::hset('channel:setting:' . $channel_id, 'tiktok_report_type', $type);
             Redis::hDel('channel:setting:' . $channel_id, 'tiktok_report_percent');
             Redis::hset('channel:setting:' . $channel_id, 'new_tiktok_report_percent', $molecule);