wesmiler 2 лет назад
Родитель
Сommit
da5af6981d

+ 109 - 3
app/Helpers/common.php

@@ -567,6 +567,16 @@ if (!function_exists('format_time')) {
     }
 }
 
+if (!function_exists('format_num')){
+    /**
+     * @param $num
+     */
+    function format_num($num, $max=10000, $text='w')
+    {
+        return $num > 10000? moneyFormat($num/$max,1).$text : $num;
+    }
+}
+
 if (!function_exists('format_bytes')) {
 
     /**
@@ -1595,9 +1605,6 @@ if (!function_exists('save_image')) {
             }
             rename($old_path, ATTACHMENT_PATH . $new_path);
 
-            $uploadFile = new UploadService();
-            $uploadFile->save($new_path, $imgExt, Config::get('constants.uploadFiles.channel.ADMIN'));
-
             return $new_path;
         } else {
             // 保存远程图片
@@ -1941,6 +1948,105 @@ if (!function_exists('upload_video')) {
     }
 }
 
+if (!function_exists('upload_base64')) {
+
+    /**
+     * 上传文件
+     * @param $base64 base64内容
+     * @return array 返回结果
+     * @author laravel开发员
+     * @date 2019/5/23
+     */
+    function upload_base64($base64, $fileType='jpg', $file_path = '', $userId = 0)
+    {
+        // 检测请求中是否包含上传的文件
+        if (empty($base64)) {
+            return false;
+        }
+
+        // 文件路径
+        $file_dir = ($file_path ? ATTACHMENT_PATH . '/base64/' . $file_path : ATTACHMENT_PATH . '/base64/files') . "/" . date('Ymd');
+
+
+        // 检测文件路径是否存在,不存在则创建
+        if (!file_exists($file_dir)) {
+            mkdir($file_dir, 0777, true);
+        }
+
+        // 文件名称
+        $file_name = uniqid() . '.' . $fileType;
+        // 保存文件内容
+        $base64 = str_replace('data:image/jpeg;base64,','',$base64);
+        file_put_contents($file_dir.$file_name,base64_decode($base64));
+        if(!file_exists($file_dir.$file_name)){
+            return false;
+        }
+
+        // 文件临时路径
+        $file_path = str_replace(ATTACHMENT_PATH, '', $file_dir) . '/' . $file_name;
+        // 返回结果
+        $result = [
+            'file_ext'           => $fileType,
+            'file_type'          => $fileType,
+            'file_name'          => $file_name,
+            'file_path'          => $file_path,
+        ];
+        return $result;
+    }
+}
+
+
+if (!function_exists('upload_remote_image')) {
+
+    /**
+     * 上传保存网络文件
+     * @param $request 网络请求
+     * @return array 返回结果
+     * @author laravel开发员
+     * @date 2019/5/23
+     */
+    function upload_remote_image($url, $fileType='jpg', $file_path = '', $userId = 0)
+    {
+        // 检测请求中是否包含上传的文件
+        if (empty($url)) {
+            return false;
+        }
+
+        // 文件路径
+        $file_dir = ($file_path ? ATTACHMENT_PATH . '/remotes/' . $file_path : ATTACHMENT_PATH . '/remotes/files') . "/" . date('Ymd');
+
+
+        // 检测文件路径是否存在,不存在则创建
+        if (!file_exists($file_dir)) {
+            mkdir($file_dir, 0777, true);
+        }
+
+        // 文件名称
+        $file_name = uniqid() . '.' . $fileType;
+        // 保存文件内容
+        $content = file_get_contents($url);
+        if(!$content){
+            return false;
+        }
+        file_put_contents($file_dir.$file_name, $content);
+        if(!file_exists($file_dir.$file_name)){
+            return false;
+        }
+
+        // 文件临时路径
+        $file_path = str_replace(ATTACHMENT_PATH, '', $file_dir) . '/' . $file_name;
+
+        // 返回结果
+        $result = [
+            'file_ext'           => $fileType,
+            'file_type'          => $fileType,
+            'file_name'          => $file_name,
+            'file_path'          => $file_path,
+        ];
+        return $result;
+    }
+}
+
 if (!function_exists('widget')) {
 
     /**

+ 1 - 2
app/Http/Controllers/Api/v1/GoodsController.php

@@ -9,8 +9,7 @@ use App\Services\Api\GoodsCategoryService;
 use App\Services\RedisService;
 
 /**
- * 商品/服务管理
- * Class CartController
+ * 商品服务管理
  * @package App\Http\Controllers\Api
  */
 class GoodsController extends webApp

+ 134 - 0
app/Http/Controllers/Api/v1/VideoController.php

@@ -0,0 +1,134 @@
+<?php
+
+namespace App\Http\Controllers\Api\v1;
+
+use App\Http\Controllers\Api\webApp;
+use App\Http\Validator\GoodsValidator;
+use App\Services\Api\GoodsService;
+use App\Services\Api\GoodsCategoryService;
+use App\Services\Api\VideoService;
+use App\Services\RedisService;
+
+/**
+ * 短视频服务管理
+ * @package App\Http\Controllers\Api
+ */
+class VideoController extends webApp
+{
+
+    /**
+     * 列表
+     * @return array
+     */
+    public function index()
+    {
+       try {
+           $params = request()->post();
+           $pageSize = request()->post('pageSize', 0);
+           $type = request()->post('type', 1);
+           // 我的视频
+           if($type == 1){
+
+           }
+           // 喜欢的视频
+           else if ($type == 2){
+
+           }
+           // 收藏的视频
+           else if ($type == 3){
+
+           }
+           // 观看历史
+           else if ($type == 4){
+
+           }
+           $datas = VideoService::make()->getDataList($params, $pageSize,'', $this->userId);
+           return message(1010, true, $datas);
+       } catch (\Exception $exception){
+           RedisService::set("caches:request:error_video_index", ['trace'=>$exception->getTrace()], 7200);
+           return message(1018, false, ['error'=>env('APP_DEBUG')? $exception->getMessage() : '']);
+       }
+    }
+
+    /**
+     * 列表
+     * @return array
+     */
+    public function list()
+    {
+        try {
+            $params = request()->post();
+            $pageSize = request()->post('pageSize', 0);
+            $datas = VideoService::make()->getDataList($params, $pageSize,'lev_a.*,lev_c.name as merch_name', $this->userId);
+            return message(1010, true, $datas);
+        } catch (\Exception $exception){
+            RedisService::set("caches:request:error_goods_index", ['trace'=>$exception->getTrace()], 7200);
+            return message(1018, false, ['error'=>env('APP_DEBUG')? $exception->getTrace() : '']);
+        }
+    }
+
+    /**
+     * 分类
+     * @return array
+     */
+    public function category()
+    {
+        $params = request()->post();
+        $pageSize = request()->post('pageSize', 99);
+        $datas = GoodsCategoryService::make()->getDataList($params, $pageSize);
+        return message(1010, true, $datas);
+    }
+
+    /**
+     * 详情
+     * @return array
+     */
+    public function info()
+    {
+        $id = request()->post('id', 0);
+        $info = GoodsService::make()->getInfo($id, $this->userId);
+        return message(1010, true, $info);
+    }
+
+
+    /**
+     * 发布
+     * @return array
+     */
+    public function publish()
+    {
+        $params = request()->all();
+        if(!$result = VideoService::make()->publish($this->userId, $params)){
+            return message(VideoService::make()->getError(), false);
+        }else{
+            return message(VideoService::make()->getError(), true, $result);
+        }
+    }
+
+    /**
+     * 状态/上下架
+     * @return array|mixed
+     */
+    public function status()
+    {
+        if(!$result = VideoService::make()->status()){
+            return message(VideoService::make()->getError(), false);
+        }else{
+            return message(VideoService::make()->getError(), true, $result);
+        }
+    }
+
+    /**
+     * 删除
+     * @return array|mixed
+     */
+    public function delete()
+    {
+        if(!$result = VideoService::make()->delete()){
+            return message(VideoService::make()->getError(), false);
+        }else{
+            return message(VideoService::make()->getError(), true);
+        }
+    }
+
+}

+ 341 - 0
app/Services/Api/VideoCollectService.php

@@ -0,0 +1,341 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Services\Api;
+
+use App\Models\MemberCollectModel;
+use App\Models\VideoCollectModel;
+use App\Models\VideoModel;
+use App\Services\BaseService;
+use App\Services\RedisService;
+use BN\Red;
+
+/**
+ * 短视频收藏点赞管理-服务类
+ * @author laravel开发员
+ * @since 2020/11/11
+ * @package App\Services\Api
+ */
+class VideoCollectService extends BaseService
+{
+    // 静态对象
+    protected static $instance = null;
+
+    /**
+     * 构造函数
+     * @author laravel开发员
+     * @since 2020/11/11
+     * MemberCollectService constructor.
+     */
+    public function __construct()
+    {
+        $this->model = new VideoCollectModel();
+    }
+
+    /**
+     * 静态入口
+     * @return static|null
+     */
+    public static function make()
+    {
+        if (!self::$instance) {
+            self::$instance = (new static());
+        }
+        return self::$instance;
+    }
+
+    /**
+     * 列表数据
+     * @param $params
+     * @param int $pageSize
+     * @return array
+     */
+    public function getDataList($userId, $params, $pageSize = 15, $field='')
+    {
+        $where = ['a.mark' => 1,'a.status'=>1,'b.status'=>1,'b.mark'=>1];
+        $field = $field? $field : 'lev_a.*,lev_b.id as cid,lev_b.user_id as collect_user_id,lev_a.type as collect_type';
+        $sortType = isset($params['sort_type']) ? $params['sort_type'] : 1;
+        $order = 'id desc';
+        if($sortType == 1){
+            $order = 'lev_b.create_time desc, lev_b.id desc';
+        }
+        $list = $this->model->with(['member'])
+            ->from('video_collect as b')
+            ->leftJoin('video as a', 'a.id', '=', 'b.collect_id')
+            ->where($where)
+            ->where(function ($query) use ($params) {
+                $userId = isset($params['user_id']) ? $params['user_id'] : 0;
+                if ($userId > 0) {
+                    $query->where('a.user_id', $userId);
+                }
+
+                $collectUserId = isset($params['collect_uid']) ? $params['collect_uid'] : 0;
+                if ($collectUserId > 0) {
+                    $query->where('a.collect_uid', $collectUserId);
+                }
+
+                $isRead = isset($params['is_read'])? $params['is_read'] : 0;
+                $isRead = $isRead>0? $isRead : 0;
+                if ($isRead > 0) {
+                    $query->where('a.is_read', $isRead);
+                }
+
+                $type = isset($params['type'])? $params['type'] : 0;
+                $type = $type>0? $type : 1;
+                if ($type > 0) {
+                    $query->where('a.type', $type);
+                }
+
+            })
+            ->where(function ($query) use ($params) {
+                $keyword = isset($params['kw']) ? $params['kw'] : '';
+                if ($keyword) {
+                    $query->where('a.title', 'like', "%{$keyword}%")
+                        ->orWhere('a.tags','like',"%{$keyword}%")
+                        ->orWhere('a.description','like',"%{$keyword}%");
+                }
+            })
+            ->selectRaw($field)
+            ->orderByRaw($order)
+            ->paginate($pageSize > 0 ? $pageSize : 9999999);
+        $list = $list ? $list->toArray() : [];
+        if ($list) {
+            foreach ($list['data'] as &$item) {
+                $item['time_text'] = isset($item['create_time']) && $item['create_time']? dateFormat($item['create_time']) : '';
+                $item['thumb'] = isset($item['thumb']) && $item['thumb'] ? get_image_url($item['thumb']) : '';
+                $item['file_url'] = isset($item['file_url']) && $item['file_url'] ? get_image_url($item['file_url']) : '';
+                if(isset($item['albums'])){
+                    $albums = $item['albums']? json_decode($item['albums'], true):[];
+                    $item['albums'] = $albums? get_images_preview($albums) : [];
+                }
+                if(isset($item['music_url'])){
+                    $item['music_url'] = $item['music_url']? get_image_url($item['music_url']) : '';
+                }
+                $member = isset($item['member'])? $item['member'] : [];
+                if($member){
+                    $member['avatar'] = isset($member['avatar'])? get_image_url($member['avatar']) : '';
+                }
+                $item['tags'] = isset($item['tags']) && $item['tags']? explode(',', $item['tags']) : [];
+                $item['like_num'] = isset($item['like_num']) && $item['like_num']? format_num($item['like_num']) : 0;
+                $item['collect_num'] = isset($item['collect_num']) && $item['collect_num']? format_num($item['collect_num']) : 0;
+                $item['views'] = isset($item['views']) && $item['views']? format_num($item['views']) : 0;
+                $item['member'] = $member;
+            }
+        }
+
+        return [
+            'pageSize' => $pageSize,
+            'total' => isset($list['total']) ? $list['total'] : 0,
+            'list' => isset($list['data']) ? $list['data'] : []
+        ];
+    }
+
+    /**
+     * 是否已经收藏或点赞过
+     * @param $userId
+     * @param $collectUid
+     * @param int $type 类型:
+     * @return array|mixed
+     */
+    public function checkCollect($userId, $collectId, $type=1)
+    {
+        $cacheKey = "caches:videos:collect:u{$userId}_c{$collectId}_{$type}";
+        $data = RedisService::get($cacheKey);
+        if($data){
+            return $data? 1: 2;
+        }
+
+        $data = $this->model->where(['user_id'=> $userId,'collect_id'=> $collectId,'type'=> $type,'status'=>1,'mark'=>1])->value('id');
+        if($data){
+            RedisService::set($cacheKey, $data, rand(5, 10));
+        }
+
+        return $data? 1 : 2;
+    }
+
+    /**
+     * 缓存信息
+     * @param $userId
+     * @param $collectId
+     * @param $type
+     * @return array|mixed
+     */
+    public function getCollectCacheInfo($userId, $collectId, $type)
+    {
+        $cacheKey = "caches:videos:collect:temp_{$userId}_{$collectId}_{$type}";
+        $info = RedisService::get($cacheKey);
+        if($info || RedisService::exists($cacheKey)){
+            return $info;
+        }
+
+        $info = $this->model->where(['user_id'=> $userId,'collect_id'=> $collectId,'type'=> $type])->select(['id','user_id','status'])->first();
+        $info = $info? $info->toArray() : [];
+        if($info){
+            RedisService::set($cacheKey, $info, rand(10,30));
+        }
+
+        return $info;
+    }
+
+    public function getRecommendData($userId)
+    {
+        $cacheKey = "caches:videos:recommend:{$userId}";
+        $data = RedisService::get($cacheKey);
+        if($data || RedisService::exists($cacheKey)){
+            return $data? $data : [];
+        }
+
+        $arr = ['uids'=>[],'tags'=>[]];
+        $datas = $this->model->where(['user_id'=> $userId,'status'=>1,'mark'=>1])
+            ->where('collect_uid','>', 0)
+            ->select(['collect_uid','tags'])
+            ->orderRaw('rand()')
+            ->limit(rand(3,5))
+            ->get();
+        $datas = $datas? $datas->toArray() : [];
+        if($datas){
+            foreach ($datas as $item)
+            {
+                $uid = isset($item['collect_uid'])? $item['collect_uid'] : 0;
+                $tags = isset($item['tags'])? explode(',', $item['tags']) : [];
+                if($uid){
+                    $arr['uids'][] = $uid;
+                }
+
+                if($tags){
+                    $tags = array_filter($tags);
+                    $arr['tags'] = array_merge($arr['tags'], $tags);
+                    $arr['tags'] = array_unique($arr['tags']);
+                }
+            }
+
+            RedisService::set($cacheKey, $arr, rand(3600, 7200));
+        }
+
+        return $arr;
+    }
+
+    /**
+     * 收藏点赞
+     * @param $userId
+     * @param $dynamicId
+     * @param $type
+     * @param int $status
+     * @return mixed
+     */
+    public function collect($userId, $params)
+    {
+        $collectId = isset($params['id'])? intval($params['id']) : 0;
+        $type = isset($params['type'])? intval($params['type']) : 2;
+        $status = isset($params['status'])? intval($params['status']) : 1;
+        if($collectId<=0 || !in_array($type, [1,2,3]) || !in_array($status, [1,2,3])){
+            $this->error = 2501;
+            return false;
+        }
+
+        $collectInfo = $this->getCollectCacheInfo($userId, $collectId, $type);
+        $id = isset($collectInfo['id'])? $collectInfo['id'] : 0;
+        $status = isset($collectInfo['status'])? $collectInfo['status'] : 0;
+        if($type==1 && $collectInfo && $status == 1){
+            $this->error = 2501;
+            return false;
+        }
+
+        // 信息
+        $info = VideoModel::where(['id'=> $collectId,'mark'=>1])->select(['id','user_id','tags'])->first();
+        $collectUid = isset($info['user_id'])? $info['user_id'] : 0;
+        if(empty($info)){
+            $this->error = 1039;
+            return false;
+        }
+
+        $data = [
+            'user_id'=> $userId,
+            'type'=> $type,
+            'collect_id'=> $collectId,
+            'collect_uid'=> $collectUid,
+            'tags'=> isset($info['tags'])? $info['tags'] : '',
+            'update_time'=> time(),
+            'status'=> $status,
+            'mark'=> 1,
+        ];
+        if(!$id){
+            $data['create_time'] = time();
+            $this->error = '1002';
+            RedisService::clear("caches:videos:collect:u{$userId}_c{$collectId}_{$type}");
+            RedisService::clear("caches:videos:collect:temp_{$userId}_{$collectId}_{$type}");
+            RedisService::clear("caches:videos:recommend:{$userId}");
+            return $this->model->insertGetId($data);
+        }else{
+            $this->error = '1002';
+            RedisService::clear("caches:videos:collect:u{$userId}_c{$collectId}_{$type}");
+            RedisService::clear("caches:videos:collect:temp_{$userId}_{$collectId}_{$type}");
+            RedisService::clear("caches:videos:recommend:{$userId}");
+            return $this->model->where('id', $id)->update($data);
+        }
+    }
+
+    /**
+     * 获取(被)收藏/关注/点赞数量
+     * @param $userId 用户ID
+     * @param int $type 类型:1-关注,2-收藏,3-点赞喜欢
+     * @param int $ctype 查询类型:1-被关注/收藏/点赞,2-关注/收藏/点赞
+     * @return array|mixed
+     */
+    public function getCount($userId, $type=1, $ctype=1)
+    {
+        $cacheKey = "caches:videos:collect:{$userId}_{$type}_{$ctype}";
+        $data = RedisService::get($cacheKey);
+        if($data){
+            return $data;
+        }
+
+        $field = 'collect_uid';
+        if($ctype == 2){
+            $field = 'user_id';
+        }
+
+        $data = $this->model->where([$field=> $userId,'type'=>$type,'status'=>1,'mark'=>1])->count('id');
+        if($data){
+            RedisService::set($cacheKey, $data, 3600);
+        }
+
+        return $data;
+    }
+
+    /**
+     * 取消
+     * @param $userId
+     * @return bool
+     */
+    public function cancel($userId)
+    {
+        // 参数
+        $ids = request()->post('ids','');
+        $ids = $ids? explode(',', $ids) : [];
+        $type = request()->post('type',0);
+        if (empty($ids) && $type == 0) {
+            $this->error = 1033;
+            return false;
+        }
+
+        if($type){
+            $this->model->where(['user_id'=> $userId,'status'=>1,'mark'=>1])->update(['status'=>2,'update_time'=>time()]);
+        }else {
+            $this->model->where(['user_id'=> $userId,'status'=>1,'mark'=>1])->whereIn('id', $ids)->update(['status'=>2,'update_time'=>time()]);
+        }
+
+        $this->error = 1002;
+        return true;
+    }
+
+
+}

+ 486 - 0
app/Services/Api/VideoService.php

@@ -0,0 +1,486 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Services\Api;
+
+use App\Models\AgentModel;
+use App\Models\GoodsModel;
+use App\Models\MemberModel;
+use App\Models\MerchantModel;
+use App\Models\OrderModel;
+use App\Models\ShopModel;
+use App\Models\TradeModel;
+use App\Models\VideoCollectModel;
+use App\Models\VideoModel;
+use App\Services\BaseService;
+use App\Services\ConfigService;
+use App\Services\RedisService;
+use Illuminate\Support\Facades\DB;
+
+/**
+ * 短视频管理-服务类
+ * @author laravel开发员
+ * @since 2020/11/11
+ * @package App\Services\Api
+ */
+class VideoService extends BaseService
+{
+    // 静态对象
+    protected static $instance = null;
+
+    /**
+     * 构造函数
+     * @author laravel开发员
+     * @since 2020/11/11
+     * GoodsService constructor.
+     */
+    public function __construct()
+    {
+        $this->model = new VideoModel();
+    }
+
+    /**
+     * 静态入口
+     * @return static|null
+     */
+    public static function make()
+    {
+        if (!self::$instance) {
+            self::$instance = (new static());
+        }
+        return self::$instance;
+    }
+
+    /**
+     * 列表数据
+     * @param $params
+     * @param int $pageSize
+     * @return array
+     */
+    public function getDataList($params, $pageSize = 18, $field = '', $userId=0)
+    {
+
+        $where = ['a.mark' => 1,'b.mark'=>1];
+        $field = $field? $field : 'lev_a.*';
+        $order = 'lev_a.id desc';
+        $sortType = isset($params['sort_type']) ? $params['sort_type'] : 0;
+        $list = $this->model->with(['member'])->from('video as a')
+            ->leftJoin('member as b', 'b.id', '=', 'a.user_id')
+            ->where($where)
+            ->where(function ($query) use ($params) {
+                $type = isset($params['type']) ? $params['type'] : 0;
+                if ($type > 0) {
+                    $query->where('a.type', $type);
+                }
+
+                $uid = isset($params['user_id']) ? $params['user_id'] : 0;
+                if ($uid > 0) {
+                    $query->where('a.user_id', $uid);
+                }else{
+                    $query->where('a.status', 2);
+                }
+            })
+            ->where(function ($query) use ($params) {
+                $keyword = isset($params['kw']) ? $params['kw'] : '';
+                if ($keyword) {
+                    $query->where('a.title', 'like', "%{$keyword}%")
+                        ->orWhere('a.tags', 'like', "%{$keyword}%")
+                        ->orWhere('a.description', 'like', "%{$keyword}%")
+                        ->orWhere('b.nickname', 'like', "%{$keyword}%");
+                }
+            })
+            ->selectRaw($field)
+            ->orderByRaw($order)
+            ->paginate($pageSize > 0 ? $pageSize : 9999999);
+
+        $list = $list ? $list->toArray() : [];
+        if ($list && $list['data']) {
+            foreach ($list['data'] as &$item) {
+                $item['create_time'] = isset($item['create_time']) ? datetime($item['create_time'], 'Y-m-d H.i.s') : '';
+                $item['thumb'] = isset($item['thumb']) && $item['thumb'] ? get_image_url($item['thumb']) : '';
+                if(isset($item['albums'])){
+                    $albums = $item['albums']? json_decode($item['albums'], true):[];
+                    $item['albums'] = $albums? get_images_preview($albums) : [];
+                }
+
+                if(isset($item['file_url'])){
+                    $item['file_url'] = $item['file_url']? get_image_url($item['file_url']) : '';
+                }
+
+                if(isset($item['music_url'])){
+                    $item['music_url'] = $item['music_url']? get_image_url($item['music_url']) : '';
+                }
+
+                $member = isset($item['member'])? $item['member'] : [];
+                if($member){
+                    $member['avatar'] = isset($member['avatar'])? get_image_url($member['avatar']) : '';
+                }
+                $item['tags'] = isset($item['tags']) && $item['tags']? explode(',', $item['tags']) : [];
+                $item['like_num'] = isset($item['like_num']) && $item['like_num']? format_num($item['like_num']) : 0;
+                $item['collect_num'] = isset($item['collect_num']) && $item['collect_num']? format_num($item['collect_num']) : 0;
+                $item['views'] = isset($item['views']) && $item['views']? format_num($item['views']) : 0;
+                $item['member'] = $member;
+            }
+        }
+
+        return [
+            'pageSize' => $pageSize,
+            'total'    => isset($list['total']) ? $list['total'] : 0,
+            'list'     => isset($list['data']) ? $list['data'] : []
+        ];
+    }
+
+    /**
+     * 列表数据
+     * @param $params
+     * @param int $pageSize
+     * @return array
+     */
+    public function getIndexList($params, $pageSize = 6, $field='', $userId=0)
+    {
+        $where = ['a.mark' => 1,'a.status'=>2,'b.mark'=>1];
+        $field = $field? $field : 'lev_a.*';
+        $order = 'rand()';
+        $model = $this->model->with(['member'])->from('video as a')
+            ->leftJoin('member as b', 'b.id', '=', 'a.user_id')
+            ->where($where)
+            ->where(function ($query) use ($params) {
+                $type = isset($params['type']) ? $params['type'] : 0;
+                if ($type > 0) {
+                    $query->where('a.type', $type);
+                }
+
+                $uid = isset($params['user_id']) ? $params['user_id'] : 0;
+                if ($uid > 0) {
+                    $query->where('a.user_id', $uid);
+                }else{
+                    $query->where('a.status', 2);
+                }
+            })
+            ->where(function ($query) use ($params) {
+                $keyword = isset($params['kw']) ? $params['kw'] : '';
+                if ($keyword) {
+                    $query->where('a.title', 'like', "%{$keyword}%")
+                        ->orWhere('a.tags', 'like', "%{$keyword}%")
+                        ->orWhere('a.description', 'like', "%{$keyword}%")
+                        ->orWhere('b.nickname', 'like', "%{$keyword}%");
+                }
+            });
+
+        // 推荐的数据
+        $countModel = clone $model;
+        $total = $countModel->where(function($query) use($params, $userId){
+            // 推荐视频数据
+            $isRecommend = isset($params['is_recommend']) ? $params['is_recommend'] : 0;
+            if ($isRecommend > 0) {
+                $recommendData = VideoCollectService::make()->getRecommendData($userId);
+                $uids = isset($recommendData['uids'])? $recommendData['uids'] : []; // 按用户推荐
+                $tags = isset($recommendData['tags'])? $recommendData['tags'] : [];  // 按标签推荐
+                if($uids){
+                    $query->orWhere(function($query) use($uids){
+                        $query->whereIn('a.user_id', $uids);
+                    });
+                }
+
+                if($tags){
+                    $query->orWhere(function($query) use($tags){
+                        foreach($tags as $tag){
+                            $query->where('a.tags', 'like',"%{$tag}%")
+                                ->orWhere('a.description','like',"%{$tag}%");
+                        }
+                    });
+                }
+            }
+        })->count('lev_a.id');
+
+        if($total > 0){
+            // 关联推荐数据
+            $list = $countModel->selectRaw($field)
+                ->orderByRaw($order)
+                ->paginate($pageSize > 0 ? $pageSize : 9999999);
+        }else{
+            // 默认推荐数据
+            $list = $model->selectRaw($field)
+                ->orderByRaw($order)
+                ->paginate($pageSize > 0 ? $pageSize : 9999999);
+        }
+
+        $list = $list ? $list->toArray() : [];
+        if ($list && $list['data']) {
+            foreach ($list['data'] as &$item) {
+                $item['create_time'] = isset($item['create_time']) ? datetime($item['create_time'], 'Y-m-d H.i.s') : '';
+                $item['thumb'] = isset($item['thumb']) && $item['thumb'] ? get_image_url($item['thumb']) : '';
+                if(isset($item['albums'])){
+                    $albums = $item['albums']? json_decode($item['albums'], true):[];
+                    $item['albums'] = $albums? get_images_preview($albums) : [];
+                }
+
+                if(isset($item['file_url'])){
+                    $item['file_url'] = $item['file_url']? get_image_url($item['file_url']) : '';
+                }
+
+                if(isset($item['music_url'])){
+                    $item['music_url'] = $item['music_url']? get_image_url($item['music_url']) : '';
+                }
+
+                $member = isset($item['member'])? $item['member'] : [];
+                if($member){
+                    $member['avatar'] = isset($member['avatar'])? get_image_url($member['avatar']) : '';
+                }
+                $item['tags'] = isset($item['tags']) && $item['tags']? explode(',', $item['tags']) : [];
+                $item['like_num'] = isset($item['like_num']) && $item['like_num']? format_num($item['like_num']) : 0;
+                $item['collect_num'] = isset($item['collect_num']) && $item['collect_num']? format_num($item['collect_num']) : 0;
+                $item['views'] = isset($item['views']) && $item['views']? format_num($item['views']) : 0;
+                $item['member'] = $member;
+            }
+        }
+
+        return [
+            'pageSize' => $pageSize,
+            'total'    => isset($list['total']) ? $list['total'] : 0,
+            'list'     => isset($list['data']) ? $list['data'] : []
+        ];
+    }
+
+    /**
+     * 详情
+     * @param $id
+     * @return array
+     */
+    public function getInfo($id, $userId=0, $field=[])
+    {
+        $field = $field? $field : ['a.*'];
+        $info = $this->model->from('video as a')->with(['member'])
+            ->leftJoin('member as b','b.id','=','a.user_id')
+            ->where(['a.id'=> $id,'a.mark'=>1,'b.mark'=>1])
+            ->select($field)
+            ->first();
+
+        $info = $info? $info->toArray() : [];
+        if($info){
+            if(isset($info['thumb'])){
+                $info['thumb'] = $info['thumb']? get_image_url($info['thumb']) : '';
+            }
+            if(isset($info['file_url'])){
+                $info['file_url'] = $info['file_url']? get_image_url($info['file_url']) : '';
+            }
+            if(isset($item['music_url'])){
+                $item['music_url'] = $item['music_url']? get_image_url($item['music_url']) : '';
+            }
+            if(isset($info['albums'])){
+                $info['albums'] = $info['albums']? json_decode($info['albums'], true) : [];
+                $info['albums'] = $info['albums']? get_images_preview($info['albums']) : [];
+            }
+
+            // 浏览历史
+            if(!VideoCollectService::make()->getCollectCacheInfo($userId, $id, 1)){
+                $data = [
+                    'user_id'=> $userId,
+                    'type'=> 1,
+                    'collect_id'=> $id,
+                    'collect_uid'=> isset($info['user_id'])? $info['user_id'] : 0,
+                    'tags'=> isset($info['tags'])? $info['tags'] : '',
+                    'create_time'=> time(),
+                    'status'=> 1,
+                ];
+                VideoCollectModel::insert($data);
+                RedisService::set("caches:videos:collect:temp_{$userId}_{$id}_1", $data, rand(10,30));
+                RedisService::clear("caches:videos:recommend:{$userId}");
+            }
+
+            // 浏览量
+            $this->updateView($userId, $id);
+        }
+
+        return $info;
+
+    }
+
+    /**
+     * 更新浏览量
+     * @param $userId
+     * @param $dynamicId
+     * @return array|mixed
+     */
+    public function updateView($userId, $id)
+    {
+        $cacheKey = "caches:videos:views:u{$userId}_d{$id}";
+        $data = RedisService::get($cacheKey);
+        if($data){
+            return false;
+        }
+
+        $data = $this->model->where(['id'=> $id])->update(['views'=>DB::raw('views + 1'),'update_time'=>time()]);
+        RedisService::set($cacheKey, $id, rand(1,3)*3600);
+        return $data;
+    }
+
+
+    /**
+     * 发布
+     * @param $goodsId
+     * @return bool
+     */
+    public function publish($userId, $params)
+    {
+        $goodsId = isset($params['goods_id'])? intval($params['goods_id']) : 0;
+        $type = isset($params['type'])? intval($params['type']) : 2;
+        $userInfo = MemberModel::where(['id'=> $userId,'mark'=>1])
+            ->select(['id','nickname','status'])
+            ->first();
+        $status = isset($userInfo['status'])? $userInfo['status'] : 0;
+        $nickname = isset($userInfo['nickname'])? $userInfo['nickname'] : '';
+        if(empty($userInfo) || $status != 1){
+            $this->error = 2017;
+            return false;
+        }
+
+        $thumb = isset($params['thumb'])? trim($params['thumb']) : '';
+        if($thumb){
+            $result = upload_base64($thumb);
+            $thumb = isset($result['file_path'])? $result['file_path'] : '';
+            if(empty($thumb)){
+                $this->error = 2208;
+                return false;
+            }
+        }
+        // 音乐
+        $musicUrl = isset($params['music_url'])? trim($params['music_url']) : '';
+        if($musicUrl){
+            $result = upload_remote_image($musicUrl,'mp3','music');
+            $musicUrl = isset($result['file_path'])? $result['file_path'] : '';
+            if(empty($musicUrl)){
+                $this->error = 2209;
+                return false;
+            }
+        }
+
+        // 视频
+        $fileUrl = isset($params['file_url'])? trim($params['file_url']) : '';
+        $albums = isset($params['albums'])? $params['albums'] : [];
+        if($type == 1) {
+            if($fileUrl){
+                $result = upload_base64($fileUrl);
+                $fileUrl = isset($result['file_path'])? $result['file_path'] : '';
+                if(empty($fileUrl)){
+                    $this->error = 2212;
+                    return false;
+                }
+            }else{
+                $this->error = 2213;
+                return false;
+            }
+        }
+
+        // 相册
+        else if($type == 2){
+            if(empty($albums) || !is_array($albums)){
+                $this->error = 2211;
+                return false;
+            }
+            $files = [];
+            foreach ($albums as $album){
+                $result = upload_base64($album);
+                $url = isset($result['file_path'])? $result['file_path'] : '';
+                if(empty($url)){
+                    $this->error = 2212;
+                    return false;
+                }
+                $files[] = ['url'=> $url];
+            }
+
+            $albums = $files;
+        }
+
+        $title = isset($params['title']) && $params['title']? trim($params['title']) : "{$nickname} 发布的短视频";
+        $description = isset($params['description']) && $params['description']? trim($params['description']) : "{$nickname} 发布的短视频";
+        $publishCheck = ConfigService::make()->getConfigByCode('video_publish_check',0);
+        $publishCheck = $publishCheck>0? $publishCheck : 0;
+        $data = [
+            'user_id'  => $userId,
+            'title'  => $title,
+            'type'  => $type,
+            'description'  => $description,
+            'tags'  =>  isset($params['tags']) && $params['tags']? implode(',', $params['tags']) : '',
+            'thumb'  => $thumb,
+            'albums'  => $albums? json_encode($albums) : '',
+            'music_hash'  => isset($params['music_hash'])? trim($params['music_hash']) : '',
+            'music_url'  => $musicUrl,
+            'goods_id'  => $goodsId,
+            'is_comment'  => isset($params['is_comment'])? intval($params['is_comment']) : 1,
+            'status'  => $publishCheck? 1 : 2,
+            'mark'  => 1,
+            'publish_at' => date('Y-m-d H:i:s'),
+            'create_time' => time(),
+        ];
+
+        if($this->model->insertGetId($data)){
+            $this->error = 1023;
+            return true;
+        }
+
+        $this->error = 1024;
+        return false;
+    }
+
+    /**
+     * 状态设置
+     * @return bool
+     */
+    public function status()
+    {
+        $id = request()->post('id', 0);
+        $status = request()->post('status', 1);
+        if ($id && !$this->model->where(['id' => $id, 'mark' => 1])->value('id')) {
+            $this->error = 2981;
+            return false;
+        }
+
+        if($this->model->where(['id'=> $id,'mark'=>1])->update(['status'=>$status, 'update_time'=> time()])){
+            $this->error = 1002;
+            return true;
+        }
+
+        $this->error = 1003;
+        return true;
+    }
+
+    /**
+     * 删除
+     * @return bool
+     */
+    public function delete()
+    {
+        // 参数
+        $param = request()->all();
+        $id   = getter($param, "id");
+        if (empty($id)) {
+            $this->error = 2014;
+            return false;
+        }
+
+        if(!$this->model->where(['id'=> $id])->value('id')){
+            $this->error = 1039;
+            return false;
+        }
+
+
+        if($this->model->where(['id'=> $id])->update(['mark'=>0,'update_time'=>time()])){
+            $this->model->where(['mark'=> 0])->where('update_time','<=', time() - 3 * 86400)->delete();
+            $this->error = 1025;
+            return true;
+        }else{
+            $this->error = 1026;
+            return false;
+        }
+    }
+
+}

+ 8 - 1
resources/lang/zh-cn/api.php

@@ -38,6 +38,7 @@ return [
     '1036' => '出帐钱包地址未配置',
     '1037' => '入账钱包地址未配置',
     '1038' => '出账钱包地址未配置或余额不足,请先充值',
+    '1039' => '数据不存在',
 
     // 登录注册
     '2001'=> '账号非法或未注册',
@@ -56,7 +57,7 @@ return [
     '2014'=> '缺少参数',
     '2015'=> '账号已被冻结,请联系客服',
     '2016'=> '微信授权失败',
-    '2017'=> '账号或已被冻结,请稍后再试或联系客服',
+    '2017'=> '账号不可用或已被冻结,请稍后再试或联系客服',
     '2018'=> '商家账号不可用或已冻结,请联系客服',
     '2019'=> '邮件接口参数未配置',
     '2020'=> '邮件验证码发送成功',
@@ -80,6 +81,12 @@ return [
     '2042'=> '开播失败',
 
     '2207'=> '没有获取到数据',
+    '2208'=> '保存封面失败,请返回重试',
+    '2209'=> '保存背景音乐文件失败,请返回重试',
+    '2210'=> '保存相册文件失败,请返回重试',
+    '2211'=> '请选择相册文件',
+    '2212'=> '保存视频文件失败,请返回重试',
+    '2213'=> '请选择或拍摄视频',
 
     
     '我正在直播,快来看看吧'=>'我正在直播,快来看看吧',

+ 5 - 0
routes/api.php

@@ -57,6 +57,11 @@ Route::prefix('v1')->group(function(){
     Route::post('/music/index', [\App\Http\Controllers\Api\v1\MusicController::class, 'index']);
     Route::post('/music/info', [\App\Http\Controllers\Api\v1\MusicController::class, 'getInfo']);
 
+    // 短视频
+    Route::post('/video/index', [\App\Http\Controllers\Api\v1\VideoController::class, 'index']);
+    Route::post('/video/info', [\App\Http\Controllers\Api\v1\VideoController::class, 'getInfo']);
+    Route::post('/video/publish', [\App\Http\Controllers\Api\v1\VideoController::class, 'publish']);
+
 
     // 会员板块
     Route::post('/user/info', [\App\Http\Controllers\Api\v1\MemberController::class, 'getInfo']);