Browse Source

Merge pull request #2051 from visuddhinanda/laravel

课程支持报名时间
visuddhinanda 2 years ago
parent
commit
184b26f683

+ 2 - 1
app/Console/Commands/MqProgress.php

@@ -47,7 +47,8 @@ class MqProgress extends Command
         $this->info(" [*] Waiting for {$queue}. To exit press CTRL+C");
         Log::debug("mq:progress start.");
         Mq::worker($exchange,$queue,function ($message){
-            $data = ['--book'=>$message->book,
+            $data = [
+                        '--book'=>$message->book,
                         '--para'=>$message->para,
                         '--channel'=>$message->channel,
                     ];

+ 1 - 1
app/Console/Commands/TestSendMail.php

@@ -45,7 +45,7 @@ class TestSendMail extends Command
         }
         $uuid = Str::uuid();
         Mail::to("visuddhinanda@gmail.com")
-            ->send(new InviteMail($uuid,'en'));
+            ->send(new InviteMail($uuid));
         if(Mail::failures()){
             $this->error('send email fail');
         }

+ 33 - 0
app/Http/Api/ChannelApi.php

@@ -51,6 +51,39 @@ class ChannelApi{
         }
         return $output;
     }
+
+    public static function userCanEdit($userUid,$channelUid){
+        $channels = ChannelApi::getCanEditByUser($userUid);
+        return in_array($channelUid,$channels);
+    }
+    public static function getCanEditByUser($userUuid=null){
+        #获取 user 在某章节 所有有权限的 channel 列表
+        $channelId = [];
+        //我自己的
+
+        if($userUuid){
+            $my = Channel::select('uid')->where('owner_uid', $userUuid)->get();
+            foreach ($my as $key => $value) {
+                $channelId[$value->uid] = $value->uid;
+            }
+
+            //获取共享channel
+
+            $allSharedChannels = ShareApi::getResList($userUuid,2);
+            foreach ($allSharedChannels as $key => $value) {
+                if($value['power'] >= 20){
+                   $channelId[$value['res_id']] = $value['res_id'];
+                }
+            }
+        }
+
+        $output = array();
+        foreach ($channelId as $key => $value) {
+            $output[] = $key;
+        }
+        return $output;
+    }
+
     public static function getSysChannel($channel_name,$fallback=""){
         $channel = Channel::where('name',$channel_name)
                     ->where('owner_uid',config("mint.admin.root_uuid"))

+ 1 - 0
app/Http/Controllers/CorpusController.php

@@ -701,6 +701,7 @@ class CorpusController extends Controller
                                             $newSent['content'] = $wbwData;
                                             $newSent['contentType'] = 'json';
                                             $newSent['html'] = "";
+                                            $newSent['studio'] = $indexChannel[$this->wbwChannels[0]]->studio;
                                         }
                                     }
                                 }else{

+ 9 - 3
app/Http/Controllers/CourseController.php

@@ -24,8 +24,10 @@ class CourseController extends Controller
 		$result=false;
 		$indexCol = ['id','title','subtitle',
                      'cover','content','content_type',
-                     'teacher','start_at','end_at','join',
-                     'publicity','updated_at','created_at'];
+                     'teacher','start_at','end_at',
+                     'sign_up_start_at','sign_up_end_at',
+                     'join','publicity',
+                     'updated_at','created_at'];
 		switch ($request->get('view')) {
             case 'new':
                 //最新公开课程列表
@@ -162,7 +164,9 @@ class CourseController extends Controller
             return $this->error(__('auth.failed'));
         }
         //查询是否重复
-        if(Course::where('title',$request->get('title'))->where('studio_id',$user['user_uid'])->exists()){
+        if(Course::where('title',$request->get('title'))
+                ->where('studio_id',$user['user_uid'])
+                ->exists()){
             return $this->error(__('validation.exists',['name']));
         }
 
@@ -242,6 +246,8 @@ class CourseController extends Controller
         if($request->has('publicity')) {$course->publicity = $request->get('publicity');}
         $course->start_at = $request->get('start_at');
         $course->end_at = $request->get('end_at');
+        $course->sign_up_start_at = $request->get('sign_up_start_at');
+        $course->sign_up_end_at = $request->get('sign_up_end_at');
         $course->join = $request->get('join');
         $course->save();
         return $this->ok($course);

+ 110 - 3
app/Http/Controllers/DiscussionController.php

@@ -9,11 +9,14 @@ use App\Models\Wbw;
 use App\Models\WbwBlock;
 use App\Models\PaliSentence;
 use App\Models\Sentence;
+use App\Models\Channel;
 use App\Http\Resources\DiscussionResource;
 use App\Http\Api\MdRender;
 use App\Http\Api\AuthApi;
 use App\Http\Api\Mq;
 use App\Http\Controllers\ArticleController;
+use App\Http\Api\UserApi;
+use App\Http\Api\ChannelApi;
 
 class DiscussionController extends Controller
 {
@@ -25,6 +28,10 @@ class DiscussionController extends Controller
     public function index(Request $request)
     {
         //
+        $user = AuthApi::current($request);
+        if($user){
+            $userInfo = UserApi::getByUuid($user['user_uid']);
+        }
 		switch ($request->get('view')) {
             case 'question-by-topic':
                 $topic = Discussion::where('id',$request->get('id'));
@@ -42,10 +49,59 @@ class DiscussionController extends Controller
                                     ->where('parent',null);
                 break;
             case 'question':
+                /**
+                 * 禁止:
+                 * 未注册用户看到任何人发表的discussion
+                 * basic用户看到别人在别人channel发表的discussion
+                 *
+                 */
+                if(!$user && $request->get('type')==='discussion'){
+                    return $this->ok([
+                        "rows" => [],
+                        "count" => 0,
+                        'active' => 0,
+                        'close' => 0,
+                        'can_create' => false,
+                        'can_reply' => false,
+                        ]);
+                }
+
+                if($user){
+                    $res_type = Discussion::where('res_id',$request->get('id'))->value('res_type');
+                    switch ($res_type) {
+                        case 'sentence':
+                            # code...
+                            break;
+                        case 'wbw':
+                            $block_uid = Wbw::where('uid',$request->get('id'))->value('block_uid');
+                            if($block_uid){
+                                $channelId = WbwBlock::where('uid',$block_uid)->value('channel_uid');
+                                if($channelId){
+                                    $canEdit = ChannelApi::userCanEdit($user['user_uid'],$channelId);
+                                }
+                            }
+                            break;
+                        default:
+                            # code...
+                            break;
+                    }
+                }
+
                 $table = Discussion::where('res_id',$request->get('id'))
                                     ->where('type', $request->get('type','discussion'))
                                     ->where('status',$request->get('status','active'))
                                     ->where('parent',null);
+                if($request->get('type')==='discussion'){
+                    if(isset($userInfo) &&
+                        isset($userInfo['roles']) &&
+                        in_array('basic',$userInfo['roles'])){
+                            if(isset($canEdit) && $canEdit===true){
+
+                            }else{
+                               $table = $table->where('editor_uid',$userInfo['id']);
+                            }
+                    }
+                }
                 $activeNumber = Discussion::where('res_id',$request->get('id'))
                                             ->where('parent',null)
                                             ->where('type', $request->get('type','discussion'))
@@ -65,7 +121,7 @@ class DiscussionController extends Controller
             case 'res_id':
                 /**
                  * 先获取顶级节点
-                 *
+                 * 需要确定用户身份,manager查看全部topic 普通用户只显示自己提交的topic
                  */
                 $roots = Discussion::where('res_id',$request->get('id'))
                                     ->where('type', $request->get('type','discussion'))
@@ -85,6 +141,27 @@ class DiscussionController extends Controller
                                             ->where('type', $request->get('type','discussion'))
                                             ->where('status','close')->count();
                 break;
+            case 'topic-by-user':
+                /**
+                 * 某用户发表的全部topic
+                 *
+                 */
+                if(!$user){
+                    return $this->error('',403,403);
+                }
+                $table = Discussion::where('editor_uid',$user['user_uid'])
+                                    ->where('type', $request->get('type','discussion'))
+                                    ->whereIn('status',explode(',',$request->get('status','active')) )
+                                    ->where('parent',null);
+                $activeNumber = Discussion::where('editor_uid',$user['user_uid'])
+                                            ->where('parent',null)
+                                            ->where('type', $request->get('type','discussion'))
+                                            ->where('status','active')->count();
+                $closeNumber = Discussion::where('editor_uid',$user['user_uid'])
+                                            ->where('parent',null)
+                                            ->where('type', $request->get('type','discussion'))
+                                            ->where('status','close')->count();
+                break;
             case 'all':
                 $table = Discussion::where('parent',null);
                 $activeNumber = Discussion::where('parent',null)
@@ -315,16 +392,46 @@ class DiscussionController extends Controller
             return $this->error(__('auth.failed'),[403],403);
         }
         //
-        if($discussion->editor_uid !== $user['user_uid']){
+        $isManager = false;
+        $isResManager = false;
+        if($discussion->editor_uid === $user['user_uid']){
+            $isManager = true;
+        }else{
+            //查看是否是资源拥有者
+            if($discussion->res_type === 'sentence'){
+                $res = Sentence::find($discussion->res_id);
+                if($res){
+                    $channelId = $res->channel_uid;
+                }
+            }else if($discussion->res_type === 'wbw'){
+                $res = Wbw::where('uid',$discussion->res_id)->first();
+                if($res){
+                    $block = WbwBlock::where('uid',$res->block_uid)->first();
+                    if($block){
+                        $channelId = $block->channel_uid;
+                    }
+                }
+            }
+            if(isset($channelId)){
+                $channel = Channel::find($channelId);
+                if($channel){
+                    if($channel->owner_uid===$user['user_uid']){
+                        $isResManager = true;
+                    }
+                }
+            }
+        }
+        if(!$isManager && !$isResManager){
             return $this->error(__('auth.failed'),[403],403);
         }
+
         $discussion->title = $request->get('title',null);
         $discussion->content = $request->get('content',null);
         $discussion->status = $request->get('status','active');
         if($request->has('type')){
             $discussion->type = $request->get('type');
         }
-        $discussion->editor_uid = $user['user_uid'];
+        //$discussion->editor_uid = $user['user_uid'];
         $discussion->save();
         return $this->ok(new DiscussionResource($discussion));
 

+ 201 - 0
app/Http/Controllers/DiscussionCountController.php

@@ -0,0 +1,201 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Log;
+use App\Models\Discussion;
+use App\Models\CourseMember;
+use App\Models\Course;
+use App\Models\Sentence;
+use App\Models\WbwBlock;
+use App\Models\Wbw;
+use App\Http\Api\AuthApi;
+use App\Http\Resources\DiscussionCountResource;
+
+
+class DiscussionCountController extends Controller
+{
+    /**
+     * Display a listing of the resource.
+     *
+     * @return \Illuminate\Http\Response
+     */
+    public function index()
+    {
+        //
+    }
+
+    /**
+     * 课程模式业务逻辑
+     * 标准答案channel:学生提问
+     * 学生channel: 老师批改作业
+     * 老师:
+     *   标准答案channel: 本期学生,老师(区分已经回复,未回复)
+     *   学生channel: 本期学生,老师
+     * 学生:
+     *   标准答案channel:我自己topic(区分已经回复,未回复)
+     *   学生自己channel: 我自己,本期老师
+     *
+     * 输入:
+     *   句子列表
+     *   courseId
+     * 返回数据
+     *  resId
+     *  type:'discussion':
+     *     my:number
+     *     myReplied:number
+     *     all:number
+     *     allReplied:number
+     * @param  \Illuminate\Http\Request  $request
+     * @return \Illuminate\Http\Response
+     */
+    public function store(Request $request)
+    {
+        /**
+         * 课程
+         * 1. 获取用户角色
+         * 2. 获取成员列表
+         * 3. 计算答案channel的结果
+         * 4. 计算作业channel的结果
+         */
+        $user = AuthApi::current($request);
+        if(!$user){
+            return $this->error('auth.failed',401,401);
+        }
+        if($request->has('course_id')){
+            //判断我的角色
+            $my = CourseMember::where('user_id',$user["user_uid"])
+                                ->where('is_current',true)
+                                ->where('course_id',$request->get('course_id'))
+                                ->first();
+            if(!$my){
+                return $this->error('auth.failed',403,403);
+            }
+            //获取全部成员列表
+            $allMembers = CourseMember::where('is_current',true)
+                                ->where('course_id',$request->get('course_id'))
+                                ->select('user_id')
+                                ->get();
+            Log::debug('allMembers',['members'=>$allMembers]);
+            //找到全部相关channel
+            $channels = array();
+            //获取答案channel
+            $answerChannel = Course::where('id',$request->get('course_id'))
+                            ->value('channel_id');
+            $exerciseChannels = CourseMember::where('is_current',true)
+                                    ->where('course_id',$request->get('course_id'))
+                                    ->select('channel_id')
+                                    ->get();
+            if($answerChannel){
+                array_push($channels,$answerChannel);
+            }
+            $users = array();
+            if($my->role === 'student'){
+                //自己的channel + 答案
+                if($my->channel_id){
+                    array_push($channels,$my->channel_id);
+                }
+            }else{
+                //找到全部学员channel + 答案
+                foreach ($exerciseChannels as $key => $value) {
+                    array_push($channels,$value->channel_id);
+                }
+            }
+        }
+
+        //获取全部资源列表
+        $resId = array();
+        $querySentId = $request->get('sentences');
+        //译文
+        $table = Sentence::select('uid')
+                        ->whereIns(['book_id','paragraph','word_start','word_end'],$querySentId);
+        if(isset($channels)){
+            $table = $table->whereIn('channel_uid',$channels);
+        }
+        $sentUid = $table->get();
+
+        foreach ($sentUid as $key => $value) {
+            $resId[] = $value->uid;
+        }
+        //wbw
+        $wbwBlockParagraphs = [];
+        foreach ($querySentId as $key => $value) {
+            $wbwBlockParagraphs[] = [$value[0],$value[1]];
+        }
+        $table = WbwBlock::select('uid')
+                          ->whereIns(['book_id','paragraph'],$wbwBlockParagraphs);
+        if(isset($channels)){
+            $table = $table->whereIn('channel_uid',$channels);
+        }
+        $wbwBlock = $table->get();
+        if($wbwBlock){
+            //找到逐词解析数据
+            foreach ($querySentId as $key => $value) {
+                $wbwData = Wbw::whereIn('block_uid',$wbwBlock)
+                                ->whereBetween('wid',[$value[2],$value[3]])
+                                ->select('uid')
+                                ->get();
+                foreach ($wbwData as $key => $value) {
+                    $resId[] = $value->uid;
+                }
+            }
+        }
+        Log::debug('res id',['res'=>$resId]);
+        //全部资源id获取完毕
+        $table = Discussion::select(['id','res_id','type','editor_uid'])
+                            ->where('status','active')
+                            ->whereNull('parent')
+                            ->whereIn('res_id',$resId);
+        if(isset($allMembers)){
+            $table = $table->whereIn('editor_uid',$allMembers);
+        }
+
+        $allDiscussions = $table->get();
+        $result = DiscussionCountResource::collection($allDiscussions);
+        Log::debug('response',['data'=>$result]);
+        return $this->ok($result);
+    }
+
+    /**
+     * Display the specified resource.
+     *
+     * @param  string  $resId
+     * @return \Illuminate\Http\Response
+     */
+    public function show(string  $resId)
+    {
+        //
+        $allDiscussions = Discussion::where('status','active')
+                                    ->whereNull('parent')
+                                    ->where('res_id',$resId)
+                                    ->select(['id','res_id','type','editor_uid'])
+                                    ->get();
+        $result = DiscussionCountResource::collection($allDiscussions);
+        Log::debug('response',['data'=>$result]);
+        return $this->ok($result);
+    }
+
+    /**
+     * Update the specified resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  \App\Models\Discussion  $discussion
+     * @return \Illuminate\Http\Response
+     */
+    public function update(Request $request, Discussion $discussion)
+    {
+        //
+    }
+
+    /**
+     * Remove the specified resource from storage.
+     *
+     * @param  \App\Models\Discussion  $discussion
+     * @return \Illuminate\Http\Response
+     */
+    public function destroy(Discussion $discussion)
+    {
+        //
+    }
+}

+ 4 - 1
app/Http/Controllers/InviteController.php

@@ -94,7 +94,10 @@ class InviteController extends Controller
 
         $uuid = Str::uuid();
         Mail::to($request->get('email'))
-            ->send(new InviteMail($uuid,$request->get('lang'),$request->get('dashboard')));
+            ->send(new InviteMail($uuid,
+                                $request->get('subject','sign up wikipali'),
+                                $request->get('lang'),
+                                $request->get('dashboard')));
         if(Mail::failures()){
             return $this->error('send email fail', '',200);
         }else{

+ 17 - 3
app/Http/Controllers/SentenceController.php

@@ -33,6 +33,7 @@ class SentenceController extends Controller
      */
     public function index(Request $request)
     {
+        $user = AuthApi::current($request);
         $result=false;
 		$indexCol = ['id','uid','book_id','paragraph',
                     'word_start','word_end','content','content_type',
@@ -148,6 +149,7 @@ class SentenceController extends Controller
                 $sent = explode('-',$request->get('sentence')) ;
                 $table = Sentence::select($indexCol)
                                 ->whereIn('channel_uid', $channels)
+                                ->where('ver','>',1)
                                 ->where('book_id',$sent[0])
                                 ->where('paragraph',$sent[1])
                                 ->where('word_start',$sent[2])
@@ -155,15 +157,25 @@ class SentenceController extends Controller
                 break;
             case 'chapter':
                 $chapter =  PaliTextApi::getChapterStartEnd($request->get('book'),$request->get('para'));
-                $table = Sentence::where('book_id',$request->get('book'))
+                $table = Sentence::where('ver','>',1)
+                                    ->where('book_id',$request->get('book'))
                                     ->whereBetween('paragraph',$chapter)
                                     ->whereIn('channel_uid',explode(',',$request->get('channels')));
                 break;
             case 'paragraph':
-                $table = Sentence::where('book_id',$request->get('book'))
+                $table = Sentence::where('ver','>',1)
+                                    ->where('book_id',$request->get('book'))
                                     ->whereIn('paragraph',explode(',',$request->get('para')))
                                     ->whereIn('channel_uid',explode(',',$request->get('channels')))
                                     ->orderBy('book_id')->orderBy('paragraph')->orderBy('word_start');
+                break;
+            case 'my-edit':
+                //我编辑的
+                if(!$user){
+                    return $this->error(__('auth.failed'),401,401);
+                }
+                $table = Sentence::where('editor_uid',$user['user_uid'])
+                                ->where('ver','>',1);
                 break;
 			default:
 				# code...
@@ -186,7 +198,9 @@ class SentenceController extends Controller
             $output = ["count"=>$count];
             if($request->get('view') === 'sent-can-read' ||
                 $request->get('view') === 'chapter' ||
-                $request->get('view') === 'paragraph'){
+                $request->get('view') === 'paragraph' ||
+                $request->get('view') === 'my-edit'
+                ){
                 $output["rows"] = SentResource::collection($result);
             }else{
                 $output["rows"] = $result;

+ 64 - 35
app/Http/Controllers/UserStatisticController.php

@@ -53,56 +53,85 @@ class UserStatisticController extends Controller
      * @param  \App\Models\UserOperationDaily  $userOperationDaily
      * @return \Illuminate\Http\Response
      */
-    public function show(string $userName)
+    public function show(Request $request,string $userName)
     {
         //
         $queryUserId = UserApi::getIntIdByName($userName);
         $queryUserUuid = UserApi::getIdByName($userName);
         $cacheExpiry = config('mint.cache.expire');
+
+        $expSum = 0;
+        $wbwCount = 0;
+        $lookupCount = 0;
+        $translationCount = 0;
+        $translationCountPub = 0;
+        $termCount = 0;
+        $termCountWithNote = 0;
+        $myDictCount = 0;
         //总经验值
-        $expSum = RedisClusters::remember("user/{$userName}/exp/sum",$cacheExpiry,function() use($queryUserId){
-			return UserOperationDaily::where('user_id',$queryUserId)
-                                     ->sum('duration');
-		});
+        if(!$request->has('view') || $request->get('view') === 'exp-sum'){
+            $expSum = RedisClusters::remember("user/{$userName}/exp/sum",$cacheExpiry,
+                    function() use($queryUserId){
+                        return UserOperationDaily::where('user_id',$queryUserId)
+                                ->sum('duration');
+            });
+        }
 
         //逐词解析
-        $wbwCount = RedisClusters::remember("user/{$userName}/wbw/count",$cacheExpiry,function() use($queryUserId){
-                    return Wbw::where('editor_id',$queryUserId)
-                        ->count();
-                        });
+        if(!$request->has('view') || $request->get('view') === 'wbw-count'){
+            $wbwCount = RedisClusters::remember("user/{$userName}/wbw/count",$cacheExpiry,
+                        function() use($queryUserId){
+                            return Wbw::where('editor_id',$queryUserId)
+                                ->count();
+                            });
+        }
+
         //查字典次数
-        $lookupCount = RedisClusters::remember("user/{$userName}/lookup/count",$cacheExpiry,function() use($queryUserId){
-                            return UserOperationLog::where('user_id',$queryUserId)
-                                                    ->where('op_type','dict_lookup')
-                                                    ->count();
-                                });
+        if(!$request->has('view') || $request->get('view') === 'lookup-count'){
+            $lookupCount = RedisClusters::remember("user/{$userName}/lookup/count",$cacheExpiry,
+                            function() use($queryUserId){
+                                return UserOperationLog::where('user_id',$queryUserId)
+                                                        ->where('op_type','dict_lookup')
+                                                        ->count();
+                                    });
+        }
         //译文
         //TODO 判断是否是译文channel
-        $translationCount = RedisClusters::remember("user/{$userName}/translation/count",$cacheExpiry,function() use($queryUserUuid){
-                            return Sentence::where('editor_uid',$queryUserUuid)
-                                           ->count();
-                            });
-        $translationCountPub = RedisClusters::remember("user/{$userName}/translation/count-pub",$cacheExpiry,function() use($queryUserUuid){
-                                    return Sentence::where('editor_uid',$queryUserUuid)
-                                    ->where('status',30)
-                                    ->count();
+        if(!$request->has('view') || $request->get('view') === 'translation-count'){
+            $translationCount = RedisClusters::remember("user/{$userName}/translation/count",$cacheExpiry,
+                                function() use($queryUserUuid){
+                                return Sentence::where('editor_uid',$queryUserUuid)
+                                            ->count();
                                 });
+            $translationCountPub = RedisClusters::remember("user/{$userName}/translation/count-pub",$cacheExpiry,
+                                    function() use($queryUserUuid){
+                                        return Sentence::where('editor_uid',$queryUserUuid)
+                                        ->where('status',30)
+                                        ->count();
+                                    });
+        }
         //术语
-        $termCount = RedisClusters::remember("user/{$userName}/term/count",$cacheExpiry,function() use($queryUserId){
-                        return DhammaTerm::where('editor_id',$queryUserId)
-                                    ->count();
-                    });
-        $termCountWithNote = RedisClusters::remember("user/{$userName}/term/count-note",$cacheExpiry,function() use($queryUserId){
-                                return DhammaTerm::where('editor_id',$queryUserId)
-                                                    ->where('note',"<>","")
-                                                    ->count();
-                                });
-        //单词本
-        $myDictCount = RedisClusters::remember("user/{$userName}/dict/count",$cacheExpiry,function() use($queryUserId){
-                            return UserDict::where('creator_id',$queryUserId)
+        if(!$request->has('view') || $request->get('view') === 'term-count'){
+            $termCount = RedisClusters::remember("user/{$userName}/term/count",$cacheExpiry,
+                        function() use($queryUserId){
+                            return DhammaTerm::where('editor_id',$queryUserId)
                                         ->count();
                         });
-
+            $termCountWithNote = RedisClusters::remember("user/{$userName}/term/count-note",$cacheExpiry,
+                                function() use($queryUserId){
+                                    return DhammaTerm::where('editor_id',$queryUserId)
+                                                        ->where('note',"<>","")
+                                                        ->count();
+                                    });
+        }
+        //单词本
+        if(!$request->has('view') || $request->get('view') === 'my-dict-count'){
+            $myDictCount = RedisClusters::remember("user/{$userName}/dict/count",$cacheExpiry,
+                            function() use($queryUserId){
+                                return UserDict::where('creator_id',$queryUserId)
+                                            ->count();
+                            });
+        }
         return $this->ok([
             "exp" => ["sum"=>(int)$expSum],
             "wbw" => ["count"=>(int)$wbwCount],

+ 2 - 0
app/Http/Resources/CourseResource.php

@@ -35,6 +35,8 @@ class CourseResource extends JsonResource
             "publicity"=> $this->publicity,
             "start_at"=> $this->start_at,
             "end_at"=> $this->end_at,
+            "sign_up_start_at"=> $this->sign_up_start_at,
+            "sign_up_end_at"=> $this->sign_up_end_at,
             "content"=> $this->content,
             "content_type"=> $this->content_type,
             "cover"=> $this->cover,

+ 19 - 0
app/Http/Resources/DiscussionCountResource.php

@@ -0,0 +1,19 @@
+<?php
+
+namespace App\Http\Resources;
+
+use Illuminate\Http\Resources\Json\JsonResource;
+
+class DiscussionCountResource extends JsonResource
+{
+    /**
+     * Transform the resource into an array.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
+     */
+    public function toArray($request)
+    {
+        return parent::toArray($request);
+    }
+}

+ 9 - 2
app/Http/Resources/SentResource.php

@@ -9,6 +9,7 @@ use App\Http\Api\UserApi;
 use App\Http\Api\ChannelApi;
 use App\Http\Api\SuggestionApi;
 use Illuminate\Support\Str;
+use Illuminate\Support\Facades\Log;
 
 class SentResource extends JsonResource
 {
@@ -21,6 +22,9 @@ class SentResource extends JsonResource
     public function toArray($request)
     {
         $channel = ChannelApi::getById($this->channel_uid);
+        if(!$channel){
+            Log::error('channel left',['data'=>$this->channel_uid,'uid'=>$this->uid]);
+        }
         if($request->get('mode','read')==="read"){
             $mode = 'read';
         }else{
@@ -36,11 +40,14 @@ class SentResource extends JsonResource
                 "word_start"=> $this->word_start,
                 "word_end"=> $this->word_end,
                 "editor"=> UserApi::getByUuid($this->editor_uid),
-                "channel"=> $channel,
-                "studio" => StudioApi::getById($channel["studio_id"]),
                 'fork_at' => $this->fork_at,
                 "updated_at"=> $this->updated_at,
             ];
+
+        if($channel){
+            $data['channel'] = $channel;
+            $data['studio'] = StudioApi::getById($channel["studio_id"]);
+        }
         if($request->has('channels')){
             $channels = explode(',',$request->get('channels'));
         }else{

+ 33 - 0
app/Http/Resources/TermResource.php

@@ -12,6 +12,7 @@ use App\Http\Api\MdRender;
 use App\Http\Api\ShareApi;
 use App\Http\Api\AuthApi;
 use App\Models\UserOperationDaily;
+use App\Models\DhammaTerm;
 
 class TermResource extends JsonResource
 {
@@ -59,6 +60,8 @@ class TermResource extends JsonResource
                 $channels = [];
             }
         }
+
+
         if(!empty($this->note)){
             $mdRender = new MdRender(
                 [
@@ -67,7 +70,37 @@ class TermResource extends JsonResource
                     'studioId'=>$this->owner,
                 ]);
             $data["html"]  = $mdRender->convert($this->note,$channels,null);
+            $summaryContent = $this->note;
+        }else if($request->has('community_summary')){
+            $lang = strtolower($this->language);
+            if($lang==='zh'){
+                $lang='zh-hans';
+            }
+            $community_channel = ChannelApi::getSysChannel("_community_term_{$lang}_");
+            if(empty($community_channel)){
+                $community_channel = ChannelApi::getSysChannel('_community_term_zh-hans_');
+            }
+            if(Str::isUuid($community_channel)){
+                            //查找社区解释
+                $community_note = DhammaTerm::where("word",$this->word)
+                                            ->where('channal',$community_channel)
+                                            ->value('note');
+                if(!empty($community_note)){
+                    $summaryContent = $community_note;
+                    $data["summary_is_community"] = true;
+                }
+            }
         }
+        if(isset($summaryContent)){
+            $mdRender = new MdRender(
+                [
+                    'mode'=>$request->get('mode','read'),
+                    'format'=>'text',
+                    'studioId'=>$this->owner,
+                ]);
+            $data["summary"]  = $mdRender->convert($summaryContent,$channels,null);
+        }
+
         $user = AuthApi::current($request);
         if(!$user){
             $data["role"] = 'reader';

+ 2 - 1
app/Mail/InviteMail.php

@@ -20,11 +20,12 @@ class InviteMail extends Mailable
      *
      * @return void
      */
-    public function __construct(string $uuid,string $lang='en-US',string $dashboard=null)
+    public function __construct(string $uuid,string $subject='wikipali invite email',string $lang='en-US',string $dashboard=null)
     {
         //
         $this->uuid = $uuid;
         $this->lang = $lang;
+        $this->subject($subject);
         if($dashboard && !empty($dashboard)){
             $this->dashboard_url = $dashboard;
         }else{

+ 3 - 1
app/Models/Course.php

@@ -18,7 +18,9 @@ class Course extends Model
         'created_at',
         'updated_at',
         'start_at',
-        'end_at'
+        'end_at',
+        'sign_up_start_at',
+        'sign_up_end_at',
     ];
 
 }

+ 2 - 2
config/mail.php

@@ -92,8 +92,8 @@ return [
     */
 
     'from' => [
-        'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'),
-        'name' => env('MAIL_FROM_NAME', 'Example'),
+        'address' => env('MAIL_FROM_ADDRESS', 'wikipali.project@gmail.com'),
+        'name' => env('MAIL_FROM_NAME', 'wikipali'),
     ],
 
     /*

+ 36 - 0
database/migrations/2024_04_14_103902_add_signup_in_courses.php

@@ -0,0 +1,36 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class AddSignupInCourses extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('courses', function (Blueprint $table) {
+            //
+            $table->timestamp('sign_up_start_at')->nullable()->index();
+            $table->timestamp('sign_up_end_at')->nullable()->index();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('courses', function (Blueprint $table) {
+            //
+            $table->dropColumn('sign_up_start_at');
+            $table->dropColumn('sign_up_end_at');
+        });
+    }
+}

+ 3 - 0
resources/mustache/chapter/html/main.html

@@ -34,6 +34,9 @@
         .origin {
             font-family: times;
         }
+        .col p{
+            display:inline;
+        }
     </style>
 </head>
 <body>

+ 2 - 0
routes/api.php

@@ -91,6 +91,7 @@ use App\Http\Controllers\WbwSentenceController;
 use App\Http\Controllers\SnowFlakeIdController;
 use App\Http\Controllers\ForgotPasswordController;
 use App\Http\Controllers\ResetPasswordController;
+use App\Http\Controllers\DiscussionCountController;
 
 /*
 |--------------------------------------------------------------------------
@@ -237,6 +238,7 @@ Route::group(['prefix' => 'v2'],function(){
     Route::apiResource('chapter-index',ChapterIndexController::class);
     Route::apiResource('wbw-sentence',WbwSentenceController::class);
     Route::apiResource('snowflake',SnowFlakeIdController::class);
+    Route::apiResource('discussion-count',DiscussionCountController::class);
 
     Route::get('download/{type1}/{type2}/{uuid}/{filename}', function ($type1,$type2,$uuid,$filename) {
         header("Content-Type: {$type1}/{$type1}");

+ 38 - 0
tests/Feature/DiscussionCountTest.php

@@ -0,0 +1,38 @@
+<?php
+
+namespace Tests\Feature;
+
+use Illuminate\Foundation\Testing\RefreshDatabase;
+use Illuminate\Foundation\Testing\WithFaker;
+use Tests\TestCase;
+
+class DiscussionCountTest extends TestCase
+{
+    private $token = 'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJuYmYiOjE2OTc3Mjg2ODUsImV4cCI6MTcyOTI2NDY4NSwidWlkIjoiYmE1NDYzZjMtNzJkMS00NDEwLTg1OGUtZWFkZDEwODg0NzEzIiwiaWQiOjR9.fiXhnY2LczZ9kKVHV0FfD3AJPZt-uqM5wrDe4EhToVexdd007ebPFYssZefmchfL0mx9nF0rgHSqjNhx4P0yDA';
+
+    /**
+     * A basic feature test example.
+     *
+     * @return void
+     */
+    public function test_example()
+    {
+        $response = $this->get('/');
+
+        $response->assertStatus(200);
+    }
+
+    public function test_store()
+    {
+        //testing store
+        $response = $this->withHeaders([
+            'Authorization' => $this->token,
+        ])->json('POST', '/api/v2/discussion-count',
+                    [
+                        'course_id'=>'b3145a94-e400-459d-9507-acbb05256e4e',
+                        'sentences'=>[[168,916,2,9]],
+                    ]);
+
+        $response->assertOk();
+    }
+}