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

Merge branch 'Haozi'

# Conflicts:
#	app/Http/Controllers/TestController.php
zhouzhendong 4 лет назад
Родитель
Сommit
3c636664aa

+ 1 - 1
app/DepartmentObligationOwner.php

@@ -21,7 +21,7 @@ class DepartmentObligationOwner extends Model
     ];
 
     public function department()
-    {   //面积报表
+    {
         return $this->hasOne(UserWorkgroup::class,"id","department_id");
     }
 }

+ 10 - 3
app/Http/Controllers/LaborReportController.php

@@ -206,7 +206,7 @@ class LaborReportController extends Controller
         if(!Gate::allows('人事管理-组长审核')){ return ["success"=>false,"data"=>"您无此权限操作!"];  }
         $id=$request->input('id');
         $relax_time=$request->input('relax_time');
-        if(!$relax_time){ return ["success"=>false,"data"=>"未选择确切晚饭时间,请重新选择!"];  }
+        if(!$relax_time){ return ["success"=>false,"data"=>"未选择用餐时间,请重新选择!"];  }
         $laborReport=LaborReport::find($id);
         $laborReportStatus=new LaborReportStatus([
             'labor_report_id'=>$id,
@@ -242,11 +242,18 @@ class LaborReportController extends Controller
     public function minusLunchTime($laborReport,$hour){
         $checkInTime=$laborReport->check_in_at;
         $checkOutTime=$laborReport->check_out_at;
-        $checkOutTime=Carbon::parse($checkOutTime)->format('H');
+        $checkOutTime=Carbon::parse($checkOutTime);
         $checkInTime=Carbon::parse($checkInTime);
-        if ($checkInTime->lessThanOrEqualTo($checkInTime->clone()->setHours(11)->setMinutes(30))&&(int)$checkOutTime>=13){
+        //白班:第一餐 默认减去1小时
+        if ($checkInTime->lessThanOrEqualTo($checkInTime->clone()->setHours(11)->setMinutes(30))//进组时间小于等于进组当天11:30
+            &&Carbon::parse($checkOutTime)->gte(Carbon::parse($checkInTime->clone()->setHour(13)->setMinute(00)->setSecond(00)))){//退组时间大于进组当天的13:00
             $hour=$hour-1;
         }
+        //夜班:第一餐 默认减去半小时
+        if ($checkInTime->lessThanOrEqualTo($checkInTime->clone()->setHours(23)->setMinutes(59))//进组时间小于等于当天23:59
+            &&Carbon::parse($checkOutTime)->gte(Carbon::parse($checkInTime->clone()->subDays(-1)->setHour(1)))){//退组时间大于等于进组后一天的1:00
+            $hour=$hour-0.5;
+        }
         return $hour;
     }
     public function updateLaborCompany(Request $request){

+ 32 - 5
app/Http/Controllers/PersonnelController.php

@@ -44,6 +44,12 @@ class PersonnelController extends Controller
             ->where('user_id',$user_id)
             ->where('created_at','like',$checkedAtDate.'%')
             ->orderBy('id','desc')->first();
+        if (!$laborReport){
+            $laborReport=LaborReport::query()->with('userDutyCheck','user.userDetail')
+                ->where('user_id',$user_id)
+                ->where('created_at','like',Carbon::parse($checked_at)->subDays()->format('Y-m-d').'%')
+                ->orderBy('id','desc')->first();
+        }
         switch ($type) {
             case '进组':
               if ($laborReport && !$laborReport->check_in_at && !$laborReport->user_workgroup_id){ //第一次进组
@@ -55,7 +61,7 @@ class PersonnelController extends Controller
                   ]);
                   LaborReportStatus::query()->create([
                       'labor_report_id'=>$laborReport['id'],
-                      'status'=>'已进组',
+                      'status'=>'已入场',
                       'created_at'=>$checked_at,
                   ]);
                   if ($remark)$laborReportService->addOrUpdateRemark($remark,$laborReport->id);
@@ -93,13 +99,19 @@ class PersonnelController extends Controller
               }
               break;
             case '退组':
-//                $laborReport=LaborReport::query()->with('userDutyCheck')
-//                    ->where('user_id',$user_id)
-//                    ->where('created_at','like',$checkedAtDate.'%')
-//                    ->orderBy('id','desc')->first();
+                $round_time=round(Carbon::parse($checked_at)->diffInSeconds(Carbon::parse($laborReport->round_check_in_at))/3600,2);
+                $relax_time=$request->input('relax_time')??null;
+                $working_duration=null;
+                if ($relax_time){
+                    $working_duration=$this->minusLunchTime($laborReport->round_check_in_at,$checked_at,$round_time)-$relax_time/60;//减去晚饭时间
+                }else{
+                    $working_duration=$this->minusLunchTime($laborReport->round_check_in_at,$checked_at,$round_time);
+                }
                 if ($laborReport && !$laborReport->check_out_at){
                     $laborReport->update([
                         'check_out_at'=>$checked_at,
+                        'relax_time'=>$relax_time,
+                        'working_duration'=>$working_duration,
                     ]);
                     LaborReportStatus::query()->create([
                         'labor_report_id'=>$laborReport['id'],
@@ -136,6 +148,21 @@ class PersonnelController extends Controller
                 return ['success'=>true,'data'=>$userDutyCheck];
         }
     }
+    public function minusLunchTime($checkInTime,$checkOutTime,$hour){
+        $checkInTime=Carbon::parse($checkInTime);
+        $checkOutTime=Carbon::parse($checkOutTime);
+        //白班:第一餐 默认减去1小时
+        if ($checkInTime->lessThanOrEqualTo($checkInTime->clone()->setHours(11)->setMinutes(30))//进组时间小于等于进组当天11:30
+            &&Carbon::parse($checkOutTime)->gte(Carbon::parse($checkInTime->clone()->setHour(13)->setMinute(00)->setSecond(00)))){//退组时间大于进组当天的13:00
+            $hour=$hour-1;
+        }
+        //夜班:第一餐 默认减去半小时
+        if ($checkInTime->lessThanOrEqualTo($checkInTime->clone()->setHours(23)->setMinutes(59))//进组时间小于等于当天23:59
+            &&Carbon::parse($checkOutTime)->gte(Carbon::parse($checkInTime->clone()->subDays(-1)->setHour(1)))){//退组时间大于等于进组后一天的1:00
+            $hour=$hour-0.5;
+        }
+        return $hour;
+    }
     //补卡创建或修改临时工报表
     public function makeOrUpdateLaborReport($userDutyCheck,$remark){
         $checkedAtDate=Carbon::parse($userDutyCheck->checked_at)->format('Y-m-d');

+ 8 - 1
app/Http/Controllers/RejectedBillItemController.php

@@ -8,6 +8,7 @@ use App\Events\InformWMSReceivedEvent;
 use App\Owner;
 use App\RejectedBill;
 use App\RejectedBillItem;
+use App\Services\RejectedBillItemService;
 use App\UploadFile;
 use App\WMSReflectReceive;
 use App\WMSReflectReceiveSku;
@@ -32,6 +33,8 @@ class RejectedBillItemController extends Controller
         if(!empty($errorFields)){
             return ['success'=>'false','error_fields'=>$errorFields,'failure_info'=>'fileds error'];
         }
+        /** @var RejectedBillItemService $service */
+        $service=app('RejectedBillItemService');
         $rejectedBillItem=RejectedBillItem::where('barcode_goods',$request->input('barcode_goods'))
             ->where('id_quality_label',$request->input('id_quality_label'))
             ->where('id_rejected_bill',$request->input('id_rejected_bill'))->first();
@@ -46,6 +49,8 @@ class RejectedBillItemController extends Controller
             $rejectedBillItem->save();
         }
 
+        $packageImage=$service->uploadImages($request->packageImages??[],$rejectedBillItem->id,'外箱');
+        $commodityImages=$service->uploadImages($request->commodityImages??[],$rejectedBillItem->id,'产品');
         if (!$rejectedBillItem->rejectedBill || !$rejectedBillItem->rejectedBill->owner)return ['success'=>'false','failure_info'=>'退货单或货主不存在'];
 
 //        /** @var CommodityService $commodityService */
@@ -320,7 +325,8 @@ class RejectedBillItemController extends Controller
         if(!$request->input('id_rejected_bill')){
             return ['success'=>'false','failure_info'=>'表头id不能为空'];
         }
-        $rejectedBillItems = RejectedBillItem::query()->with(['uploadFiles'])->where('id_rejected_bill',$request->input('id_rejected_bill'))->get();
+        $rejectedBillItems = RejectedBillItem::query()->with(['uploadFiles','packageImages','commodityImages'])
+            ->where('id_rejected_bill',$request->input('id_rejected_bill'))->get();
         return ['success'=>'true','items'=>$rejectedBillItems];
     }
     public function apiDelete(Request $request)
@@ -377,6 +383,7 @@ class RejectedBillItemController extends Controller
                     "table_id"=>$id,
                     "url"=>'/files/'.$fileName,
                     "type"=>$fileExtension,
+                    "file_name"=>$request->type??'',
                 ]);
                 if ($uploadFile->save())
                     app('LogService')->log(__CLASS__,'退货详情图片上传',json_encode($request),Auth::user()['id']);

+ 3 - 1
app/Http/Controllers/UserDutyCheckController.php

@@ -48,7 +48,8 @@ class UserDutyCheckController extends Controller
         $user_id = Cache::get('dutyCheckTokenStr_'.$userLaborToken);
         if (!$user_id) app('LogService')->log(__METHOD__, "进出场扫码(未绑定设备)__" . __FUNCTION__, json_encode($importAndExportQRCodeType));
         if ($userLaborToken && $user_id) {
-            $userDetail = UserDetail::find($user_id);
+            $userDetail = UserDetail::query()->find($user_id);
+            if ($userDetail->black_status==1)return "<h1 style='color: darkred;text-align:center'>系统识别此用户异常,请联系管理员!</h1>";
             if($userDetail){
                 if($importAndExportQRCodeType=='import') return redirect('personnel/checking-in/userDutyCheck/updateUserLaborCompanies/' . $userDetail->mobile_phone)->with("importAndExportQRCodeType", $importAndExportQRCodeType);
                 $userDutyCheck = $this->importAndExportDutyCheck($user_id, $importAndExportQRCodeType);
@@ -77,6 +78,7 @@ class UserDutyCheckController extends Controller
         $mobile_phone = $request->input('mobile_phone');
         $this->validatorPhone($request)->validate();
         $userDetail = UserDetail::query()->where('mobile_phone', $mobile_phone)->first();
+        if ($userDetail->black_status==1)return "<h1 style='color: darkred;text-align:center'>系统识别此用户异常,请联系管理员!</h1>";
         if (!$userDetail) return redirect('personnel/checking-in/userDutyCheck/createUserDetail/' . $mobile_phone)->with("importAndExportQRCodeType", $importAndExportQRCodeType);
         if (Cache::has('dutyCheckTokenUser_'.$userDetail->user_id)) return "<h1 style='color: red;text-align:center'>请使用原有设备进行打卡,如无法使用原有设备请联系管理人员解绑设备!</h1>";
         if($importAndExportQRCodeType=='import') return redirect('personnel/checking-in/userDutyCheck/updateUserLaborCompanies/' . $userDetail->mobile_phone)->with("importAndExportQRCodeType", $importAndExportQRCodeType);

+ 18 - 0
app/Http/Controllers/UserLaborController.php

@@ -72,6 +72,24 @@ class UserLaborController extends Controller
         $userLabor=UserLabor::with(['userDetail','laborCompany'])->find($id);
         return view('maintenance.userLabor.show',['userLabor'=>$userLabor]);
     }
+    //拉黑
+    public function black(Request $request){
+        if(!Gate::allows('临时工-查询')){ return redirect(url('/'));  }
+        $user_id=$request->input('user_id');
+        if (!$user_id)return ['error'=>'提交ID失败!'];
+        $userLabor=UserLabor::query()->with(['userDetail'])->find($user_id);
+        $userLabor->userDetail->update(['black_status'=>1]);
+        return ['success'=>true,'data'=>$userLabor];
+    }
+    //取消拉黑
+    public function cancelBlack(Request $request){
+        if(!Gate::allows('临时工-查询')){ return redirect(url('/'));  }
+        $user_id=$request->input('user_id');
+        if (!$user_id)return ['error'=>'提交ID失败!'];
+        $userLabor=UserLabor::query()->with(['userDetail'])->find($user_id);
+        $userLabor->userDetail->update(['black_status'=>0]);
+        return ['success'=>true,'data'=>$userLabor];
+    }
     //获取劳务记录
     public function getWorkRecord(Request $request){
         if(!Gate::allows('临时工-查询')){ return redirect(url('/'));  }

+ 21 - 42
app/LaborReport.php

@@ -25,8 +25,8 @@ class LaborReport extends Model
         'user_duty_check_id','relax_time','remark'
     ];
     protected $appends = [
-        'is_exportGroup',/*'sequence',*//*'amountOfJoined',*/'thisRecordOnlineTime','thisRecordWorkingTime','thisRoundRecordWorkingTime',
-        /*'totalOnlineTime',*/'verifyPerson','userDutyCheckVerifyUserId','isAdult','round_check_in_at','round_check_out_at','has_group_verify_right',
+        'is_exportGroup','thisRecordOnlineTime','thisRecordWorkingTime','thisRoundRecordWorkingTime',
+        'verifyPerson','userDutyCheckVerifyUserId','isAdult','round_check_in_at','round_check_out_at','has_group_verify_right',
     ];
     protected $tempFields = [
         'temEnteringRecord',
@@ -63,6 +63,7 @@ class LaborReport extends Model
         return $this->hasMany(get_class($this),'enter_number','enter_number');
     }
 
+    //进组取整时间
     public function getRoundCheckInAtAttribute(){
         if (!$this['check_in_at'])return null;
         $round_check_in_at=Carbon::parse($this['check_in_at'])->format('i');
@@ -70,6 +71,7 @@ class LaborReport extends Model
         if ($round_check_in_at>5&&$round_check_in_at<=35) return Carbon::parse($this['check_in_at'])->clone()->setMinutes(30)->setSeconds(00)->format('Y-m-d H:i:s');
         if ($round_check_in_at>35&&$round_check_in_at<=59) return Carbon::parse($this['check_in_at'])->clone()->addHour()->setMinutes(00)->setSeconds(00)->format('Y-m-d H:i:s');
     }
+    //退组取整时间
     public function getRoundCheckOutAtAttribute(){
         if (!$this['check_out_at'])return null;
         $round_check_out_at=Carbon::parse($this['check_out_at'])->format('i');
@@ -107,15 +109,6 @@ class LaborReport extends Model
     public function getUserDutyCheckVerifyUserIdAttribute(){
         return $this['userDutyCheck']['verify_user_id']?$this['userDutyCheck']['verify_user_id']:'';
     }
-    //总在线时长
-//    public function getTotalOnlineTimeAttribute(){
-//        if(self::$withoutAppends) {
-//            $totalOnlineTime = $this->laborReports->reduce(function ($value, $laborReport) {
-//                return ($value ?? 0) + $laborReport['thisRecordOnlineTime'];
-//            });
-//            return $totalOnlineTime;
-//        }
-//    }
     //总工作时长
     public function getTotalWorkingTimeAttribute(){
         if(self::$withoutAppends) {
@@ -166,19 +159,19 @@ class LaborReport extends Model
         if ($this['check_in_at']&&!$this['check_out_at']&&!$this['relax_time']) {
             $workingTime = round(Carbon::parse(Carbon::now())->diffInSeconds(Carbon::parse($this['check_in_at'])) / 3600, 2);
             $checkInTime = Carbon::parse($this['check_in_at']);
-            $checkOutTime = Carbon::parse(Carbon::now())->format('H');
+            $checkOutTime = Carbon::parse(Carbon::now());
             return $this->minusLunchTime($checkInTime, $checkOutTime, $workingTime);
         }
         if ($this['check_in_at']&&$this['check_out_at']&&!$this['relax_time']){
             $workingTime=round(Carbon::parse($this['check_out_at'])->diffInSeconds(Carbon::parse($this['check_in_at']))/3600,2);
             $checkInTime=Carbon::parse($this['check_in_at']);
-            $checkOutTime=Carbon::parse($this['check_out_at'])->format('H');
+            $checkOutTime=Carbon::parse($this['check_out_at']);
             return  $this->minusLunchTime($checkInTime,$checkOutTime,$workingTime);
         }
         if ($this['check_in_at']&&$this['check_out_at']&&$this['relax_time']){
             $workingTime=round(Carbon::parse($this['check_out_at'])->diffInSeconds(Carbon::parse($this['check_in_at']))/3600,2);
             $checkInTime=Carbon::parse($this['check_in_at']);
-            $checkOutTime=Carbon::parse($this['check_out_at'])->format('H');
+            $checkOutTime=Carbon::parse($this['check_out_at']);
             return  $this->minusLunchTime($checkInTime,$checkOutTime,$workingTime)-$this['relax_time']/60;
         }
 
@@ -189,55 +182,39 @@ class LaborReport extends Model
             if ($this['round_check_in_at'] && !$this['round_check_out_at'] && !$this['relax_time']) {
                 $workingTime = round(Carbon::parse(Carbon::now())->diffInSeconds(Carbon::parse($this['round_check_in_at'])) / 3600, 2);
                 $checkInTime = Carbon::parse($this['round_check_in_at']);
-                $checkOutTime = Carbon::parse(Carbon::now())->format('H');
+                $checkOutTime = Carbon::parse(Carbon::now());
                 return $this->minusLunchTime($checkInTime, $checkOutTime, $workingTime);
             }
             if ($this['round_check_in_at'] && $this['round_check_out_at'] && !$this['relax_time']) {
                 $workingTime = round(Carbon::parse($this['round_check_out_at'])->diffInSeconds(Carbon::parse($this['round_check_in_at'])) / 3600, 2);
                 $checkInTime = Carbon::parse($this['round_check_in_at']);
-                $checkOutTime = Carbon::parse($this['round_check_out_at'])->format('H');
+                $checkOutTime = Carbon::parse($this['round_check_out_at']);
                 return $this->minusLunchTime($checkInTime, $checkOutTime, $workingTime);
             }
             if ($this['round_check_in_at'] && $this['round_check_out_at'] && $this['relax_time']) {
                 $workingTime = round(Carbon::parse($this['round_check_out_at'])->diffInSeconds(Carbon::parse($this['round_check_in_at'])) / 3600, 2);
                 $checkInTime = Carbon::parse($this['round_check_in_at']);
-                $checkOutTime = Carbon::parse($this['round_check_out_at'])->format('H');
+                $checkOutTime = Carbon::parse($this['round_check_out_at']);
                 return $this->minusLunchTime($checkInTime, $checkOutTime, $workingTime) - $this['relax_time'] / 60;
             }
 
     }
 
-    //工作时长减午饭休息时间
+    //工作时长默认休息时间
     public function minusLunchTime($checkInTime,$checkOutTime,$hour){
-        if ($checkInTime->lessThanOrEqualTo($checkInTime->clone()->setHours(11)->setMinutes(30))&&(int)$checkOutTime>=13){
+        //白班:第一餐 默认减去1小时
+        if ($checkInTime->lessThanOrEqualTo($checkInTime->clone()->setHours(11)->setMinutes(30))//进组时间小于等于进组当天11:30
+            &&Carbon::parse($checkOutTime)->gte(Carbon::parse($checkInTime->clone()->setHour(13)->setMinute(00)->setSecond(00)))){//退组时间大于进组当天的13:00
             $hour=$hour-1;
         }
+        //夜班:第一餐 默认减去半小时
+        if ($checkInTime->lessThanOrEqualTo($checkInTime->clone()->setHours(23)->setMinutes(59))//进组时间小于等于当天23:59
+            &&Carbon::parse($checkOutTime)->gte(Carbon::parse($checkInTime->clone()->subDays(-1)->setHour(1)))){//退组时间大于等于进组后一天的1:00
+            $hour=$hour-0.5;
+        }
         return $hour;
     }
 
-    //转场序号
-//    public function getSequenceAttribute()
-//    {
-//        if(self::$withoutAppends) {
-//            if (Arr::has($this->tempFields, 'sequence')) return $this->tempFields['sequence'];
-//            foreach ($this->laborReports as $i => $laborReport) {
-//                if ($laborReport['id'] == $this['id']) {
-//                    $this->tempFields['sequence'] = $i + 1;
-//                    return $this->tempFields['sequence'];
-//                }
-//            }
-//        }
-//    }
-//    public function getAmountOfJoinedAttribute()
-//    {
-//        if(self::$withoutAppends) {
-//            if (Arr::has($this->tempFields, 'amountOfJoined')) return $this->tempFields['amountOfJoined'];
-//            $this->tempFields['amountOfJoined'] = count($this->laborReports);
-//            return $this->tempFields['amountOfJoined'];
-//        }
-//    }
-
-
     private function checkExitStatus()
     {
         $status = $this->laborReportStatus->sortByDesc('id')->first();
@@ -251,6 +228,7 @@ class LaborReport extends Model
     private function checkAmountOfJoined(){
         if ($this->amountOfJoined!=count($this->laborReports))$this->amountOfJoined=count($this->laborReports);
     }
+    //转组序号
     private function checkSequence(){
         if (!$this->sequence) foreach ($this->laborReports as $i => $laborReport) {
             if ($laborReport['id'] == $this['id']) {
@@ -258,6 +236,7 @@ class LaborReport extends Model
             }
         }
     }
+    //总在线时长
     private function checkTotalOnlineTime(){
         if (!$this->totalOnlineTime) $this->totalOnlineTime = $this->laborReports->reduce(function ($value, $laborReport) {
             return ($value ?? 0) + $laborReport['thisRecordOnlineTime'];

+ 13 - 1
app/RejectedBillItem.php

@@ -35,8 +35,20 @@ class RejectedBillItem extends Model
     public function quality(){
         return $this->belongsTo(QualityLabel::class, 'id_quality_label', 'id');
     }
+    public function packageImages(){
+        return $this->hasMany(UploadFile::class,'table_id','id')
+            ->where('table_name','rejected_bill_items')
+            ->where('file_name','外箱');
+    }
+    public function commodityImages(){
+        return $this->hasMany(UploadFile::class,'table_id','id')
+            ->where('table_name','rejected_bill_items')
+            ->where('file_name','产品');
+    }
     public function uploadFiles(){
-        return $this->hasMany(UploadFile::class,'table_id','id')->where('table_name','rejected_bill_items');
+        return $this->hasMany(UploadFile::class,'table_id','id')
+            ->where('table_name','rejected_bill_items')
+            ->whereNull('file_name');
     }
     public function wmsReflectSku(){
         $bill=$this->rejectedBill()->first();

+ 37 - 0
app/Services/RejectedBillItemService.php

@@ -3,7 +3,12 @@
 namespace App\Services;
 
 use App\RejectedBillItem;
+use App\Traits\ModelLogChanging;
 use App\Traits\ServiceAppAop;
+use App\UploadFile;
+use Illuminate\Support\Facades\Auth;
+use Intervention\Image\Facades\Image;
+use Ramsey\Uuid\Uuid;
 
 
 class RejectedBillItemService
@@ -11,5 +16,37 @@ class RejectedBillItemService
     use ServiceAppAop;
     protected $modelClass=RejectedBillItem::class;
 
+    public function uploadImages($files,$id,$type): int
+    {
+        if (!$files) return 1; //无图片上传
+        foreach ($files as $file) {
+            if (!$file->isValid()) return 2;//找不到图片
+            $tmpFile = $file->getRealPath();
+            if (!is_uploaded_file($tmpFile)) return 3;//文件错误
+            $fileExtension = $file->getClientOriginalExtension();
+            $fileName = date('ymd') . '-' . Uuid::uuid1();//thumbnail common bulky
+            $thumbnailName = storage_path('app/public/files/' . $fileName . '-thumbnail.' . $fileExtension);
+            $commonName = storage_path('app/public/files/' . $fileName . '-common.' . $fileExtension);
+            $bulkyName = storage_path('app/public/files/' . $fileName . '-bulky.' . $fileExtension);
+            $result = move_uploaded_file($tmpFile, $bulkyName);
+            if ($result) {
+                $img = Image::make($bulkyName);
+                if ($img->height() > $img->width())
+                    $img->heighten(250)->save($commonName);
+                else $img->widen(250)->save($commonName);
+                $img->heighten(28)->save($thumbnailName);
+                /** @var UploadFile|\stdClass $uploadFile */
+                $uploadFile = new UploadFile([
+                    "table_name" => "rejected_bill_items",
+                    "table_id" => $id,
+                    "url" => '/files/' . $fileName,
+                    "type" => $fileExtension,
+                    "file_name" => $type,
+                ]);
+                if ($uploadFile->save()) return 0;//上传成功
+            }
+        }
+    }
+
 
 }

+ 2 - 1
app/Services/RejectedService.php

@@ -24,7 +24,8 @@ class RejectedService
     private function  conditionQuery(array $param)
     {
         $owners = Auth::user() ? (app('UserService')->getPermittingOwnerIds(Auth::user()) ?? []) : [];
-        $rejectedBills = RejectedBill::query()->with('user','owner', 'logistic', 'items.quality', 'items.uploadFiles','orderIssueRejectedBill:logistic_number_return')
+        $rejectedBills = RejectedBill::query()->with('user','owner', 'logistic', 'items.quality',
+            'items.packageImages','items.commodityImages','items.uploadFiles','orderIssueRejectedBill:logistic_number_return')
             ->orderBy('rejected_bills.id', 'desc')
             ->whereIn('rejected_bills.id_owner', $owners);
         if (array_search("397",$owners)!==false){

+ 1 - 1
app/UserDetail.php

@@ -17,7 +17,7 @@ class UserDetail extends Model
     public $incrementing=false;
 
     protected $fillable=[
-        'user_id','full_name','gender','identity_number','mobile_phone','type','procurement_wechat_open_id'
+        'user_id','full_name','gender','identity_number','mobile_phone','type','procurement_wechat_open_id','black_status'
     ];
     protected $appends=[
         'user_labor_company'

+ 29 - 0
database/migrations/2021_11_18_141236_change_inventory_accounts_type_columns.php

@@ -0,0 +1,29 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Schema;
+
+class ChangeInventoryAccountsTypeColumns extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        DB::statement("ALTER TABLE inventory_accounts MODIFY COLUMN type ENUM('全盘','动盘','局部盘点','日循环盘')");
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        DB::statement("ALTER TABLE inventory_accounts MODIFY COLUMN type ENUM('全盘','动盘','局部盘点')");
+    }
+}

+ 32 - 0
database/migrations/2021_11_19_134704_add_black_status_column_to_user_details.php

@@ -0,0 +1,32 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class AddBlackStatusColumnToUserDetails extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('user_details', function (Blueprint $table) {
+            $table->tinyInteger("black_status")->default(0)->comment("是否拉黑");
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('user_details', function (Blueprint $table) {
+            $table->dropColumn("black_status");
+        });
+    }
+}

+ 1 - 1
resources/views/customer/project/part/_two.blade.php

@@ -41,7 +41,7 @@
 <div class="row mt-3">
     <label for="jg" class="col-2 text-info">加工组</label>
     <select id="jg" v-model="owner.jg"  class="form-control form-control-sm col-4 mb-0" :class="errors.jg ? 'is-invalid' : ''" >
-        <option v-for="userGroup in userGroups" :value="userGroup.id" v-if="userGroup.warehouse_id == owner.warehouse_id">@{{ userGroup.name }}</option>
+        <option v-for="userGroup in userGroups" :value="userGroup.id">@{{ userGroup.name }}</option>
     </select>
     <label class="col-2"><input type="text" class="form-control form-control-sm rounded-pill" placeholder="输入关键字加工组" @change="filterjg($event)"></label>
     <span class="invalid-feedback offset-2 mt-0" role="alert" v-if="errors.jg">

+ 53 - 0
resources/views/maintenance/userLabor/index.blade.php

@@ -94,6 +94,13 @@
                         @can('临时工-编辑')
                             <button class="btn btn-sm btn-outline-primary" @click="edit(userLabor.user_id)">改</button>
                             <button class="btn btn-sm btn-outline-success" @click="conversion(userLabor)">转正</button>
+                            <span v-if="userLabor.user_detail && userLabor.user_detail.black_status==0">
+                                <button class="btn btn-sm btn-outline-secondary" @click="black(userLabor.user_id)">拉黑</button>
+                            </span>
+                            <span v-if="userLabor.user_detail && userLabor.user_detail.black_status==1">
+                                <button class="btn btn-sm btn-outline-secondary" @click="cancelBlack(userLabor.user_id)">取消拉黑</button>
+                            </span>
+
                         @endcan
                         @can('临时工-删除')
                             <button class="btn btn-sm btn-outline-danger" @click="destroy(userLabor)">删</button> @endcan
@@ -148,6 +155,52 @@
                 show(user_id){
                     window.open("{{url('maintenance/userLabor')}}/"+user_id);
                 },
+                black(user_id){
+                    let _this=this;
+                    axios.post("{{url('maintenance/userLabor/black')}}",{user_id:user_id})
+                        .then(function (response) {
+                            if (response.data.error){
+                                tempTip.setDuration(3000);
+                                tempTip.show(response.data.error);
+                                return;
+                            }else {
+                                _this.userLabors.forEach(function (userLabor){
+                                    if (userLabor.user_id==response.data.data.user_id){
+                                        userLabor.user_detail=response.data.data.user_detail;
+                                        _this.$forceUpdate();
+                                    }
+                                })
+                                tempTip.setDuration(3000);
+                                tempTip.showSuccess('拉黑临时工成功!');
+                            }
+                        }).catch(function (err) {
+                        tempTip.setDuration(3000);
+                        tempTip.show('拉黑临时工失败!网络错误:' + err);
+                        });
+                },
+                cancelBlack(user_id){
+                    let _this=this;
+                    axios.post("{{url('maintenance/userLabor/cancelBlack')}}",{user_id:user_id})
+                        .then(function (response) {
+                            if (response.data.error){
+                                tempTip.setDuration(3000);
+                                tempTip.show(response.data.error);
+                                return;
+                            }else {
+                                _this.userLabors.forEach(function (userLabor){
+                                    if (userLabor.user_id==response.data.data.user_id){
+                                        userLabor.user_detail=response.data.data.user_detail;
+                                        _this.$forceUpdate();
+                                    }
+                                })
+                                tempTip.setDuration(3000);
+                                tempTip.showSuccess('取消拉黑临时工成功!');
+                            }
+                        }).catch(function (err) {
+                        tempTip.setDuration(3000);
+                        tempTip.show('取消拉黑临时工失败!网络错误:' + err);
+                        });
+                },
                 workRecord(user_id){
                     let _this=this;
                     axios.post("{{url('maintenance/userLabor/getWorkRecord')}}",{user_id:user_id})

+ 10 - 1
resources/views/personnel/checking-in/createReplenishClock.blade.php

@@ -19,6 +19,7 @@
                         <th>添加所需备注</th>
                         <th>补卡类型</th>
                         <th>工作组</th>
+                        <th>用餐时间</th>
                         <th>操作</th>
                     </tr>
                     </thead>
@@ -55,6 +56,12 @@
                             </select>
                             <small v-if="errors.type && errors.type.length>0 " class="text-danger">@{{ errors.type[0] }}</small>
                         </td>
+                        <td>
+                            <select v-if="userLabor.userDutyCheck_type=='退组'" class="form-control" id="relax_time" v-model="userLabor.relax_time">
+                                <option value="30">30分</option>
+                                <option value="60">60分</option>
+                            </select>
+                        </td>
                         <td><button @click="storeReplenishClock(userLabor)" class="btn btn-info w-100">提交补卡</button></td>
                     </tr>
                     </tbody>
@@ -115,13 +122,15 @@
                     let type=userLabor.userDutyCheck_type;
                     let remark=userLabor.laborReport_remark;
                     let userWorkGroup=userLabor.userWorkGroup;
+                    let relax_time=userLabor.relax_time;
                     if ((type==='进组')&& !userWorkGroup){
                         tempTip.setDuration(4000);
                         tempTip.show('工作组不可为空!');
                         return;
                     }
                     let _this=this;
-                    axios.post("{{url('personnel/checking-in/storeReplenishClock')}}",{user_id:user_id,checked_at:checked_at,type:type,remark:remark,userWorkGroup:userWorkGroup})
+                    axios.post("{{url('personnel/checking-in/storeReplenishClock')}}",{user_id:user_id,checked_at:checked_at,type:type,
+                        remark:remark,userWorkGroup:userWorkGroup,relax_time:relax_time})
                         .then(function (response) {
                             if (response.data.success){
                                 _this.userLabors.every(function (userLabor) {

+ 3 - 45
resources/views/personnel/laborReport/index.blade.php

@@ -164,7 +164,7 @@
             <div class="modal-dialog">
                 <div class="modal-content">
                     <div class="modal-header">
-                        <h5 class="modal-title" id="exampleModalLabel">餐时长</h5>
+                        <h5 class="modal-title" id="exampleModalLabel">餐时长</h5>
                         <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                             <span aria-hidden="true">&times;</span>
                         </button>
@@ -172,7 +172,7 @@
                     <div class="modal-body">
                         <form>
                             <div class="form-group">
-                                <label for="relax_time" class="col-form-label">选择晚饭时长:</label>
+                                <label for="relax_time" class="col-form-label">选择用餐时长:</label>
                                 <select class="form-control" id="relax_time" v-model="relax_time">
                                     <option value="30">30分</option>
                                     <option value="60">60分</option>
@@ -221,7 +221,7 @@
             <div class="modal-dialog">
                 <div class="modal-content">
                     <div class="modal-body">
-                        <b class="font-weight-bold">是否晚餐?</b>
+                        <b class="font-weight-bold">是否用餐?</b>
                     </div>
                     <div class="modal-footer">
                         <button type="button" class="close" data-dismiss="modal" aria-label="Close">
@@ -327,10 +327,6 @@
                         Echo.channel('{{$laravelEchoPrefix}}'+tokenOfBroadcastEnterAndLeave).listen('ImportEvent',(e)=>{
                             let labor=e.laborReport;
                             laborReports.unshift(labor);
-
-                            // setTimeout(function () {
-                            //     window.location.reload();
-                            // },500);
                         });
                     }
                     //退场
@@ -338,18 +334,6 @@
                         setTimeout(function () {
                             window.location.reload();
                         },500);
-                        // let labor=e.laborReport;
-                        // laborReports.every(function (laborReport) {
-                        //     if (laborReport.id==labor.id){
-                        //         laborReport.thisRecordOnlineTime=labor.thisRecordOnlineTime;
-                        //         laborReport.thisRecordWorkingTime=labor.thisRecordWorkingTime;
-                        //         laborReport.is_export=labor.is_export;
-                        //         laborReport.exit_at=labor.exit_at;
-                        //         laborReport.remark=labor.remark;
-                        //         return false
-                        //     }
-                        //     return true;
-                        // });
                     });
                     //门卫审核
                     Echo.channel('{{$laravelEchoPrefix}}userDutyCheck').listen('GuardAuditEvent',(e)=>{
@@ -383,32 +367,6 @@
                     //进组
                     _this.permittingWorkgroups.forEach(function(workgroup){
                         Echo.channel('{{$laravelEchoPrefix}}'+workgroup.token).listen('ClockinEvent',(e)=>{
-                            // let res=false;
-                            // let labor=e.laborReport;
-                            // laborReports.forEach(function (item){
-                            //     if(item.id==labor.id){
-                            //         res=true;
-                            //     }
-                            // })
-                            // if (res){
-                            //     laborReports.every(function (laborReport) {
-                            //         if (laborReport.id==labor.id){
-                            //             laborReport.userWorkGroupName=labor.user_workgroup.name;
-                            //             laborReport.has_group_verify_right=labor.has_group_verify_right;
-                            //             laborReport.user_workgroup_id=labor.user_workgroup_id;
-                            //             laborReport.checkInAt=labor.check_in_at;
-                            //             laborReport.round_check_in_at=labor.round_check_in_at;
-                            //             return false
-                            //         }
-                            //         return true;
-                            //     });
-                            // }else {
-                            //     labor.userWorkGroupName=labor.user_workgroup.name;
-                            //     labor.checkInAt=labor.check_in_at;
-                            //     labor.has_group_verify_right=labor.has_group_verify_right;
-                            //     laborReports.push(labor);
-                            // }
-
                             setTimeout(function () {
                                 window.location.reload();
                             },500);

+ 189 - 1
resources/views/rejected/create.blade.php

@@ -278,6 +278,8 @@
                                     <th class="text-center">效期</th>
                                     <th class="text-center">批次号</th>
                                     <th class="text-center">备注</th>
+                                    <th class="text-center">外箱图</th>
+                                    <th class="text-center">产品图</th>
                                     <th class="text-center">照片</th>
                                     @can('退货管理-删除')
                                         <th class="text-center">操作</th>@endcan
@@ -293,6 +295,30 @@
                                     <td>@{{item.validity_at}}</td>
                                     <td>@{{item.batch_number}}</td>
                                     <td>@{{item.remark}}</td>
+                                    <td>
+                                        <div align="center" @mouseleave="removeCommonImg('common_img_package'+item.id)" @mouseenter="commonImg('img_package'+item.id,item.package_images)">
+                                            <div>
+                                                <input class="btn  btn-sm btn-outline-secondary" type="button" @click="certiimg(item.id,'外箱')" value="上传图片 "/>
+                                                <input multiple type="file" @change="submitImages($event,i)" :id="item.id"
+                                                       style="display: none" accept="image/gif,image/jpeg,image/jpg,image/png,image/svg"/>
+                                            </div>
+                                            <div :id="'img_package'+item.id">
+                                                <img v-for="uploadFile in item.package_images"  :src="imgPrefix+uploadFile.url+'-thumbnail.'+uploadFile.type">
+                                            </div>
+                                        </div>
+                                    </td>
+                                    <td>
+                                        <div align="center" @mouseleave="removeCommonImg('common_img_commodity'+item.id)" @mouseenter="commonImg('img_commodity'+item.id,item.commodity_images)">
+                                            <div>
+                                                <input class="btn  btn-sm btn-outline-secondary" type="button" @click="certiimg(item.id,'产品')" value="上传图片 "/>
+                                                <input multiple type="file" @change="submitImages($event,i)" :id="item.id"
+                                                       style="display: none" accept="image/gif,image/jpeg,image/jpg,image/png,image/svg"/>
+                                            </div>
+                                            <div :id="'img_commodity'+item.id">
+                                                <img v-for="uploadFile in item.commodity_images"  :src="imgPrefix+uploadFile.url+'-thumbnail.'+uploadFile.type">
+                                            </div>
+                                        </div>
+                                    </td>
                                     <td>
                                         <div align="center" @mouseleave="removeCommonImg('common_img_'+item.id)" @mouseenter="commonImg('img_'+item.id,item.upload_files)">
                                             <button class="btn btn-outline-secondary btn-sm" @click="takePhoto(item.id,i)">拍照上传</button>
@@ -420,6 +446,48 @@
                                     </div>
                                 </td>
                             </tr>
+                            <tr v-if="!status.itemEditing">
+                                <td>
+                                    <div class="form-group mb-0">
+                                        <label for="package-image" class="col-form-label text-right">外箱图</label>
+                                        <div class="border border-secondary h-auto" id="package-image" style="min-height: 65px"
+                                             contenteditable="true"
+                                             @paste="pasteImage($event,itemInputting.packageImages)">
+                                            <div v-for="(image,i) in itemInputting.packageImages"
+                                                 class="d-inline-block col-4 position-relative card">
+                                                <div class="card-body">
+                                                    <img :src="image.src" class="card-img-top" :alt="image.file.name">
+                                                    <div class="float-right position-relative" >
+                                                        <button type="button" class="btn btn-sm btn-outline-danger"
+                                                                @click="spliceImage(i,itemInputting.packageImages)">取消
+                                                        </button>
+                                                    </div>
+                                                </div>
+                                            </div>
+                                        </div>
+                                    </div>
+                                </td>
+                                <td>
+                                    <div class="form-group mb-0">
+                                        <label for="commodity-image" class="col-form-label text-right">产品图</label>
+                                        <div class="border border-secondary h-auto" id="commodity-image" style="min-height: 65px"
+                                             contenteditable="true"
+                                             @paste="pasteImage($event,itemInputting.commodityImages)">
+                                            <div v-for="(image,i) in itemInputting.commodityImages"
+                                                 class="d-inline-block col-4 position-relative card">
+                                                <div class="card-body">
+                                                    <img :src="image.src" class="card-img-top" :alt="image.file.name">
+                                                    <div class="float-right position-relative">
+                                                        <button type="button" class="btn btn-sm btn-outline-danger"
+                                                                @click="spliceImage(i,itemInputting.commodityImages)">取消
+                                                        </button>
+                                                    </div>
+                                                </div>
+                                            </div>
+                                        </div>
+                                    </div>
+                                </td>
+                            </tr>
                             <tr>
                                 <td>
                                     <div class="form-group mb-0 align-items-center row">
@@ -578,6 +646,7 @@
                 itemInputting: {
                     barcode_goods: "", name_goods: "", amount: "1", id_quality_label: "",
                     batch_number: "", validity_at: "", remark: "", made_at: "",
+                    packageImages: [], commodityImages: [],
                 },
                 billInputting: {
                     id_owner: "", mobile_sender: "", sender: "", order_number: "", remark: "",
@@ -593,6 +662,7 @@
                     batch_number: "", validity_at: "", remark: "", made_at: "",
                 },
                 rejectedBills: {!! $rejectedBills??[] !!},
+                submitImageType:'',
                 items: [],
                 owners: [
                         @foreach($owners as $owner)
@@ -661,6 +731,43 @@
                     });
 
                 },
+                spliceImage(i, images) {
+                    if (!confirm('是否取消选择该图片')) return;
+                    images.splice(i, 1);
+                },
+                getImages(images) {
+                    return images.map((item) => {
+                        return item.file;
+                    })
+                },
+                pasteImage(event,imageArray){
+                    for (let i = 0; i < event.clipboardData.items.length; i++) {
+                        let item = event.clipboardData.items[i];
+                        if (item.kind === 'string') continue;
+                        if (item.type.indexOf('image') === -1) continue;
+                        if (item.kind === 'file'){
+                            let blob = item.getAsFile();
+                            let src = null;
+                            this.blobToBase64(blob).then(res => {
+                                src  = res;
+                                imageArray.push({src:res,file:blob});
+                            });
+                        }
+                    }
+                    event.preventDefault();
+                },
+                blobToBase64(blob) {
+                    return new Promise((resolve, reject) => {
+                        const fileReader = new FileReader();
+                        fileReader.onload = (e) => {
+                            resolve(e.target.result);
+                        };
+                        fileReader.readAsDataURL(blob);
+                        fileReader.onerror = () => {
+                            reject(new Error('blobToBase64 error'));
+                        };
+                    });
+                },
                 barcode_goodsChange: function (e) {
                     let _this = this;
                     let barcode = $(e.target).val();
@@ -875,8 +982,46 @@
                         alert('连接错误:' + response)
                     });
                 },
+                checkImageWhetherNeed(item){
+                    if (item.id_quality_label!=1){
+                        if (item.commodityImages.length===0){
+                            tempTip.setDuration(3000);
+                            tempTip.show('非正品,请上传外箱图及产品图!');
+                            return 1;
+                        }
+                    }
+                    return 0;
+                },
+                setFormDataImage(formData, prefix, images) {
+                    images.forEach((item) => {
+                        formData.append(`${prefix}[]`, item);
+                    });
+                },
+                getDamagedFormData(item){
+                    let _this=this;
+                    let formData = new FormData();
+                    if (item.packageImages.length>0){
+                        let packageImages = _this.getImages(item.packageImages);
+                        this.setFormDataImage(formData,'packageImages',packageImages);
+                    }
+                    if (item.commodityImages.length>0){
+                        let commodityImages = _this.getImages(item.commodityImages);
+                        this.setFormDataImage(formData,'commodityImages',commodityImages);
+                    }
+                    formData.append('barcode_goods',item.barcode_goods);
+                    formData.append('amount',item.amount);
+                    formData.append('name_goods',item.name_goods);
+                    formData.append('id_quality_label',item.id_quality_label);
+                    formData.append('batch_number',item.batch_number);
+                    formData.append('validity_at',item.validity_at);
+                    formData.append('made_at',item.made_at);
+                    formData.append('remark',item.remark);
+                    formData.append('id_rejected_bill',item.id_rejected_bill);
+                    return formData;
+                },
                 commitItem: function () {
                     let _this = this;
+                    if (_this.checkImageWhetherNeed(_this.itemInputting)===1)return;
                     let url = '{{url('apiLocal/rejectedBillItem/store')}}';
                     _this.itemInputting.id_rejected_bill = _this.status.editingBill.id;
                     if (_this.items.length < 1) {
@@ -888,7 +1033,9 @@
                             _this.isChangeOwner(_this.itemInputting.id_rejected_bill);
                         }
                     }
-                    axios.post(url, _this.itemInputting).then(function (response) {
+                    let formData = _this.getDamagedFormData(_this.itemInputting);
+
+                    axios.post(url, formData,{'Content-Type':'multipart/form-data'}).then(function (response) {
                         _this.cleanError();
                         if (response.data.success === 'true') {
                             tempTip.setDuration(1000);
@@ -1185,6 +1332,10 @@
                         return true;
                     });
                     if (itemTarget) {
+                        // itemTarget.packageImages = itemTarget.package_images;//package_images
+                        // itemTarget.commodityImages = itemTarget.commodity_images;//commodity_images
+                        // delete itemTarget.package_images;
+                        // delete itemTarget.commodity_images;
                         this.itemInputting = JSON.parse(JSON.stringify(itemTarget));
                         this.shiftToEditItem();
                         this.setEditingItem(itemTarget.id)
@@ -1325,6 +1476,34 @@
                         return "上传成功";
                     },false,true);
                 },
+                certiimg(id,type){
+                    this.submitImageType=type;
+                    $('#'+id).click();
+                },
+                submitImages(e,index){
+                    let type=this.submitImageType;
+                    let files=e.target.files;
+                    window.tempTip.setDuration(3000);
+                    if (files.length===0){window.tempTip.show("未选定图片!");return;}
+                    let formData=new FormData();
+                    for (let i=0;i<files.length;i++){
+                        if (files[i].size >=5242880){window.tempTip.show("图片大小不能超过5MB!");return;}
+                        formData.append("files[]",files[i]);
+                    }
+                    formData.append("id",this.items[index].id);
+                    formData.append("type",type);
+                    window.tempTip.postBasicRequest('{{url('apiLocal/rejectedBillItem/apiUpload')}}',formData,res=>{
+                       if (type==='外箱'){
+                           if (this.items[index].package_images.length===0) this.$set(this.items[index],'package_images',res);
+                           else this.$set(this.items[index],'package_images',this.items[index].package_images.concat(res));
+                       }
+                       if (type==='产品'){
+                           if (this.items[index].commodity_images.length===0) this.$set(this.items[index],'commodity_images',res);
+                           else this.$set(this.items[index],'commodity_images',this.items[index].commodity_images.concat(res));
+                       }
+                        return "上传成功";
+                    },false,true);
+                },
                 removeCommonImg(id){
                     $('#'+id).remove();
                 },
@@ -1350,6 +1529,7 @@
                     this.destroyImg(id,url);
                 },
                 destroyImg(id,url = null){
+                    id= id.replace(/[^0-9]/ig,"");//抽取数字部分
                     window.tempTip.postBasicRequest('{{url('apiLocal/rejectedBillItem/apiDeleteImg')}}',{id:id,url:url},()=>{
                         if (url){
                             this.items.some((item,i)=>{
@@ -1357,12 +1537,20 @@
                                     item.upload_files.some((file,j)=>{
                                         if (file.url === url){this.$delete(this.items[i].upload_files,j);return true;}
                                     });
+                                    item.package_images.some((file,j)=>{
+                                        if (file.url === url){this.$delete(this.items[i].package_images,j);return true;}
+                                    });
+                                    item.commodity_images.some((file,j)=>{
+                                        if (file.url === url){this.$delete(this.items[i].commodity_images,j);return true;}
+                                    });
                                     return true;
                                 }
                             });
                         }else{
                             this.items.forEach((item,i)=>{
                                 if (id.includes(item.id))this.$set(this.items[i],'upload_files',[]);
+                                if (id.includes(item.id))this.$set(this.items[i],'commodity_images',[]);
+                                if (id.includes(item.id))this.$set(this.items[i],'package_images',[]);
                             });
                         }
                         return "删除成功";

+ 185 - 2
resources/views/rejected/edit.blade.php

@@ -240,6 +240,8 @@
                                     <th class="text-center">效期</th>
                                     <th class="text-center">批次号</th>
                                     <th class="text-center">备注</th>
+                                    <th class="text-center">外箱图</th>
+                                    <th class="text-center">产品图</th>
                                     <th class="text-center">照片</th>
                                     @can('退货管理-删除')<th class="text-center">操作</th>@endcan
                                 </tr>
@@ -254,6 +256,30 @@
                                     <td>@{{item.validity_at}}</td>
                                     <td>@{{item.batch_number}}</td>
                                     <td>@{{item.remark}}</td>
+                                    <td>
+                                        <div align="center" @mouseleave="removeCommonImg('common_img_package'+item.id)" @mouseenter="commonImg('img_package'+item.id,item.package_images)">
+                                            <div>
+                                                <input class="btn  btn-sm btn-outline-secondary" type="button" @click="certiimg(item.id,'外箱')" value="上传图片 "/>
+                                                <input multiple type="file" @change="submitImages($event,i)" :id="item.id"
+                                                       style="display: none" accept="image/gif,image/jpeg,image/jpg,image/png,image/svg"/>
+                                            </div>
+                                            <div :id="'img_package'+item.id">
+                                                <img v-for="uploadFile in item.package_images"  :src="imgPrefix+uploadFile.url+'-thumbnail.'+uploadFile.type">
+                                            </div>
+                                        </div>
+                                    </td>
+                                    <td>
+                                        <div align="center" @mouseleave="removeCommonImg('common_img_commodity'+item.id)" @mouseenter="commonImg('img_commodity'+item.id,item.commodity_images)">
+                                            <div>
+                                                <input class="btn  btn-sm btn-outline-secondary" type="button" @click="certiimg(item.id,'产品')" value="上传图片 "/>
+                                                <input multiple type="file" @change="submitImages($event,i)" :id="item.id"
+                                                       style="display: none" accept="image/gif,image/jpeg,image/jpg,image/png,image/svg"/>
+                                            </div>
+                                            <div :id="'img_commodity'+item.id">
+                                                <img v-for="uploadFile in item.commodity_images"  :src="imgPrefix+uploadFile.url+'-thumbnail.'+uploadFile.type">
+                                            </div>
+                                        </div>
+                                    </td>
                                     <td>
                                         <div align="center" @mouseleave="removeCommonImg('common_img_'+item.id)" @mouseenter="commonImg('img_'+item.id,item.upload_files)">
                                             <button class="btn btn-outline-secondary btn-sm" @click="takePhoto(item.id,i)">拍照上传</button>
@@ -362,6 +388,48 @@
                                     </div>
                                 </td>
                             </tr>
+                            <tr v-if="!status.itemEditing">
+                                <td>
+                                    <div class="form-group mb-0">
+                                        <label for="package-image" class="col-form-label text-right">外箱图</label>
+                                        <div class="border border-secondary h-auto" id="package-image" style="min-height: 65px"
+                                             contenteditable="true"
+                                             @paste="pasteImage($event,itemInputting.packageImages)">
+                                            <div v-for="(image,i) in itemInputting.packageImages"
+                                                 class="d-inline-block col-4 position-relative card">
+                                                <div class="card-body">
+                                                    <img :src="image.src" class="card-img-top" :alt="image.file.name">
+                                                    <div class="float-right position-relative" >
+                                                        <button type="button" class="btn btn-sm btn-outline-danger"
+                                                                @click="spliceImage(i,itemInputting.packageImages)">取消
+                                                        </button>
+                                                    </div>
+                                                </div>
+                                            </div>
+                                        </div>
+                                    </div>
+                                </td>
+                                <td>
+                                    <div class="form-group mb-0">
+                                        <label for="commodity-image" class="col-form-label text-right">产品图</label>
+                                        <div class="border border-secondary h-auto" id="commodity-image" style="min-height: 65px"
+                                             contenteditable="true"
+                                             @paste="pasteImage($event,itemInputting.commodityImages)">
+                                            <div v-for="(image,i) in itemInputting.commodityImages"
+                                                 class="d-inline-block col-4 position-relative card">
+                                                <div class="card-body">
+                                                    <img :src="image.src" class="card-img-top" :alt="image.file.name">
+                                                    <div class="float-right position-relative">
+                                                        <button type="button" class="btn btn-sm btn-outline-danger"
+                                                                @click="spliceImage(i,itemInputting.commodityImages)">取消
+                                                        </button>
+                                                    </div>
+                                                </div>
+                                            </div>
+                                        </div>
+                                    </div>
+                                </td>
+                            </tr>
                             <tr>
                                 <td>
                                     <div class="form-group mb-0 align-items-center row" >
@@ -495,6 +563,7 @@
                 stopRecordCallback:'',
                 // 用于存放是否开启了视频录制
                 videoEnabled:false,
+                submitImageType:'',
 
                 status: {billCreating:true,billEditing:false,itemCreating:true,itemEditing:false
                     ,editingBill:null,editingBillId:'',editingItem:null,editingItemId:''
@@ -502,7 +571,7 @@
                     existItemsBeforeAdd:0},
                 itemInputting:{
                     barcode_goods:"",name_goods:"",amount:"1",id_quality_label:"",
-                    batch_number:"",validity_at:"",remark:"",made_at:"",
+                    batch_number:"",validity_at:"",remark:"",made_at:"",packageImages:[],commodityImages:[],
                 },
                 billInputting:{
                     id_owner:"",mobile_sender:"",sender:"",order_number:"",remark:"",
@@ -756,11 +825,88 @@
                         alert('连接错误:'+response)
                     });
                 },
+                spliceImage(i, images) {
+                    if (!confirm('是否取消选择该图片')) return;
+                    images.splice(i, 1);
+                },
+                getImages(images) {
+                    return images.map((item) => {
+                        return item.file;
+                    })
+                },
+                pasteImage(event,imageArray){
+                    for (let i = 0; i < event.clipboardData.items.length; i++) {
+                        let item = event.clipboardData.items[i];
+                        if (item.kind === 'string') continue;
+                        if (item.type.indexOf('image') === -1) continue;
+                        if (item.kind === 'file'){
+                            let blob = item.getAsFile();
+                            let src = null;
+                            this.blobToBase64(blob).then(res => {
+                                src  = res;
+                                imageArray.push({src:res,file:blob});
+                            });
+                        }
+                    }
+                    event.preventDefault();
+                },
+                blobToBase64(blob) {
+                    return new Promise((resolve, reject) => {
+                        const fileReader = new FileReader();
+                        fileReader.onload = (e) => {
+                            resolve(e.target.result);
+                        };
+                        fileReader.readAsDataURL(blob);
+                        fileReader.onerror = () => {
+                            reject(new Error('blobToBase64 error'));
+                        };
+                    });
+                },
+                checkImageWhetherNeed(item){
+                    if (item.id_quality_label!=1){
+                        if (item.commodityImages.length===0){
+                            tempTip.setDuration(3000);
+                            tempTip.show('非正品,请上传外箱图及产品图!');
+                            return 1;
+                        }
+                    }
+                    return 0;
+                },
+                setFormDataImage(formData, prefix, images) {
+                    images.forEach((item) => {
+                        formData.append(`${prefix}[]`, item);
+                    });
+                },
+                getDamagedFormData(item){
+                    let _this=this;
+                    let formData = new FormData();
+                    if (item.packageImages.length>0){
+                        let packageImages = _this.getImages(item.packageImages);
+                        this.setFormDataImage(formData,'packageImages',packageImages);
+                    }
+                    if (item.commodityImages.length>0){
+                        let commodityImages = _this.getImages(item.commodityImages);
+                        this.setFormDataImage(formData,'commodityImages',commodityImages);
+                    }
+                    formData.append('barcode_goods',item.barcode_goods);
+                    formData.append('amount',item.amount);
+                    formData.append('name_goods',item.name_goods);
+                    formData.append('id_quality_label',item.id_quality_label);
+                    formData.append('batch_number',item.batch_number);
+                    formData.append('validity_at',item.validity_at);
+                    formData.append('made_at',item.made_at);
+                    formData.append('remark',item.remark);
+                    formData.append('id_rejected_bill',item.id_rejected_bill);
+                    return formData;
+                },
                 commitItem:function () {
                     let _this=this;
+                    if (_this.checkImageWhetherNeed(_this.itemInputting)===1)return;
                     let url='{{url('apiLocal/rejectedBillItem/store')}}';
                     _this.itemInputting.id_rejected_bill=_this.status.editingBill.id;
-                    axios.post(url,_this.itemInputting).then(function (response) {
+                    let formData = _this.getDamagedFormData(_this.itemInputting);
+
+                    axios.post(url,formData,{'Content-Type':'multipart/form-data'}).then(function (response) {
                         _this.cleanError();
                         if(response.data.success==='true'){
                             tempTip.setDuration(1000);
@@ -1085,6 +1231,34 @@
                 removeCommonImg(id){
                     $('#'+id).remove();
                 },
+                certiimg(id,type){
+                    this.submitImageType=type;
+                    $('#'+id).click();
+                },
+                submitImages(e,index){
+                    let type=this.submitImageType;
+                    let files=e.target.files;
+                    window.tempTip.setDuration(3000);
+                    if (files.length===0){window.tempTip.show("未选定图片!");return;}
+                    let formData=new FormData();
+                    for (let i=0;i<files.length;i++){
+                        if (files[i].size >=5242880){window.tempTip.show("图片大小不能超过5MB!");return;}
+                        formData.append("files[]",files[i]);
+                    }
+                    formData.append("id",this.items[index].id);
+                    formData.append("type",type);
+                    window.tempTip.postBasicRequest('{{url('apiLocal/rejectedBillItem/apiUpload')}}',formData,res=>{
+                        if (type==='外箱'){
+                            if (this.items[index].package_images.length===0) this.$set(this.items[index],'package_images',res);
+                            else this.$set(this.items[index],'package_images',this.items[index].package_images.concat(res));
+                        }
+                        if (type==='产品'){
+                            if (this.items[index].commodity_images.length===0) this.$set(this.items[index],'commodity_images',res);
+                            else this.$set(this.items[index],'commodity_images',this.items[index].commodity_images.concat(res));
+                        }
+                        return "上传成功";
+                    },false,true);
+                },
                 commonImg(id,uploadFiles){
                     let div = "";
                     let isBtn = '@can('运输管理-运单-图片删除') true @endcan ';
@@ -1107,6 +1281,7 @@
                     this.destroyImg(id,url);
                 },
                 destroyImg(id,url = null){
+                    id= id.replace(/[^0-9]/ig,"");//抽取数字部分
                     window.tempTip.postBasicRequest('{{url('apiLocal/rejectedBillItem/apiDeleteImg')}}',{id:id,url:url},()=>{
                         if (url){
                             this.items.some((item,i)=>{
@@ -1114,12 +1289,20 @@
                                     item.upload_files.some((file,j)=>{
                                         if (file.url === url){this.$delete(this.items[i].upload_files,j);return true;}
                                     });
+                                    item.package_images.some((file,j)=>{
+                                        if (file.url === url){this.$delete(this.items[i].package_images,j);return true;}
+                                    });
+                                    item.commodity_images.some((file,j)=>{
+                                        if (file.url === url){this.$delete(this.items[i].commodity_images,j);return true;}
+                                    });
                                     return true;
                                 }
                             });
                         }else{
                             this.items.forEach((item,i)=>{
                                 if (id.includes(item.id))this.$set(this.items[i],'upload_files',[]);
+                                if (id.includes(item.id))this.$set(this.items[i],'commodity_images',[]);
+                                if (id.includes(item.id))this.$set(this.items[i],'package_images',[]);
                             });
                         }
                         return "删除成功";

+ 23 - 7
resources/views/rejected/search/general.blade.php

@@ -89,13 +89,13 @@
                         @cannot('退货管理-客户不可见')<td class="text-muted">@{{rejectedBill.common_02}}</td>@endcannot
                         <td class="text-muted"><span>@{{rejectedBill.goods_amount}}</span></td>
                         <td style="min-width: 1500px">
-                            <div class="w-100 p-0" :class="rejectedBill.items.length>1 ? 'up' : ''" :id="'rejected-'+rejectedBill.id" >
-                                <div class="row m-0 p-0" v-for="(item,i) in rejectedBill.items">
+                            <div class="w-100" :class="rejectedBill.items.length>1 ? 'up' : ''" :id="'rejected-'+rejectedBill.id" >
+                                <div class="row m-0" v-for="(item,i) in rejectedBill.items">
                                     @if($ownerSign)
                                     <div class="col-1 border border-1" style="overflow-x: hidden">
                                         <div class="w-100 text-overflow-warp-200 warp-min-200">@{{ (item.barcode && item.barcode.commodity) ? item.barcode.commodity.sku : '' }}</div>
                                     </div>@endif
-                                        <div title="双击展开全部" @dblclick="barcodeGoodsLength(item)"  class="border border-1" :class="item.barcode_goods_show_long ? 'col-auto' : '@if($ownerSign)col-2 @else col-3 @endif'" style="overflow-x: hidden">
+                                        <div title="双击展开全部" @dblclick="barcodeGoodsLength(item)"  class="border border-1" :class="item.barcode_goods_show_long ? 'col-auto' : '@if($ownerSign)col-1 @else col-1 @endif'" style="overflow-x: hidden">
                                             <div class="w-100 text-overflow-warp-200 warp-min-200">@{{item.barcode_goods}}</div>
                                         </div>
                                     <div title="双击展开全部" @dblclick="goodsNameLength(item)"  class="border border-1" :class="item.name_goods_show_long ? 'col-auto' : 'col-1'" style="overflow-x: hidden">
@@ -106,6 +106,20 @@
                                     <div class="col-1 border border-1">@{{item.batch_number}}</div>
                                     <div class="col-1 border border-1">@{{item.made_at}}</div>
                                     <div class="col-1 border border-1">@{{item.validity_at}}</div>
+                                        <div class="col-1 border border-1">
+                                            <div align="center" @mouseleave="removeCommonImg('common_img_package'+item.id)" @mouseenter="commonImg('img_package'+item.id,item.package_images)">
+                                                <div :id="'img_package'+item.id">
+                                                    <img v-for="uploadFile in item.package_images"  :src="imgPrefix+uploadFile.url+'-thumbnail.'+uploadFile.type">
+                                                </div>
+                                            </div>
+                                        </div>
+                                        <div class="col-1 border border-1">
+                                            <div align="center" @mouseleave="removeCommonImg('common_img_commodity'+item.id)" @mouseenter="commonImg('img_commodity'+item.id,item.commodity_images)">
+                                                <div :id="'img_commodity'+item.id">
+                                                    <img v-for="uploadFile in item.commodity_images"  :src="imgPrefix+uploadFile.url+'-thumbnail.'+uploadFile.type">
+                                                </div>
+                                            </div>
+                                        </div>
                                     <div class="col-1 border border-1">
                                         <div align="center" @mouseleave="removeCommonImg('common_img_'+item.id)" @mouseenter="commonImg('img_'+item.id,item.upload_files)">
                                             <div :id="'img_'+item.id">
@@ -113,7 +127,7 @@
                                             </div>
                                         </div>
                                     </div>
-                                    <div class="col-2 border border-1">@{{item.remark}}</div>
+                                    <div class="col-1 border border-1">@{{item.remark}}</div>
                                 </div>
                             </div>
                             <div class="text-center cursor-pointer" v-if="rejectedBill.items.length>1" @click="unfold(rejectedBill.id)">
@@ -260,16 +274,18 @@
                         @cannot('退货管理-客户不可见'){name:'common_02',value: '重量'},@endcannot
                     {name:'goods_amount',value: '商品总数'},
                     {name:"goods",type:"multi",title:"商品信息",rows:[
-                            @if($ownerSign){value:"商品SKU",col:"1"},{value:"商品条码",col:"2"},
-                                @else{value:"商品条码",col:"3"},@endif
+                            @if($ownerSign){value:"商品SKU",col:"1"},{value:"商品条码",col:"1"},
+                                @else{value:"商品条码",col:"1"},@endif
                             {value:"商品名称",col:"1"},
                             {value:"数量",col:"1"},
                             {value:"质量",col:"1"},
                             {value:"批次号",col:"1"},
                             {value:"产期",col:"1"},
                             {value:"效期",col:"1"},
+                            {value:"外箱图",col:"1"},
+                            {value:"产品图",col:"1"},
                             {value:"照片",col:"1"},
-                            {value:"备注",col:"2"},
+                            {value:"备注",col:"1"},
                         ]},
                     {name:'remark',value: '退单备注'},
                     {name:'operator_name',value: '录入人'},

+ 2 - 0
routes/web.php

@@ -171,6 +171,8 @@ Route::group(['middleware'=>'auth'],function ($route){
             Route::post('getClockRecord', 'UserLaborController@getClockRecord');
             Route::post('relieve', 'UserLaborController@relieve');
             Route::post('conversion', 'UserLaborController@conversion');
+            Route::post('black', 'UserLaborController@black');//拉黑
+            Route::post('cancelBlack', 'UserLaborController@cancelBlack');//取消拉黑
         });
         /** 纸箱 */
         Route::group(['prefix'=>'paperBox'],function(){