|
|
@@ -14,6 +14,7 @@ use App\Model\ItemNode;
|
|
|
use App\Model\ItemNodeDetails;
|
|
|
use App\Model\ItemNodeEmployee;
|
|
|
use App\Model\ItemNodeMission;
|
|
|
+use App\Model\ItemNodeMissionContent;
|
|
|
use App\Model\ItemNodeMissionDetails;
|
|
|
use App\Model\ItemNodeMissionEmployee;
|
|
|
use App\Model\SysOssTasks;
|
|
|
@@ -1379,6 +1380,8 @@ class ItemService extends Service
|
|
|
|
|
|
$model = new ItemNodeMission();
|
|
|
$model->item_id = $data['item_id'] ?? 0;
|
|
|
+ $model->item_node_id = $data['item_node_id'] ?? 0;
|
|
|
+ $model->parent_item_node_mission_id = $data['parent_item_node_mission_id'] ?? 0;
|
|
|
$tableName = $model->getTable();
|
|
|
$model->code = $this->generateBillNo([
|
|
|
'top_depart_id' => $user['top_depart_id'],
|
|
|
@@ -1570,12 +1573,200 @@ class ItemService extends Service
|
|
|
$customer['mission_title'] = $node_tmp['title'] ?? '';
|
|
|
$customer['mission_code'] = $node_tmp['code'] ?? '';
|
|
|
|
|
|
+ $item_node_map = $this->getItemNodeMap($customer['id']);
|
|
|
+ $customer['item_node_title'] = $item_node_map[$customer['id']];
|
|
|
+
|
|
|
$details = $this->getNodeMissionDetail($data['id']);
|
|
|
$customer = array_merge($customer, $details);
|
|
|
|
|
|
return [true, $customer];
|
|
|
}
|
|
|
|
|
|
+ public function itemNodeMissionUpdateProgressContent($data, $user){
|
|
|
+ if(empty($data['id'])) return [false, '任务ID不能为空'];
|
|
|
+ $customer = ItemNodeMission::where('del_time',0)
|
|
|
+ ->where('id',$data['id'])
|
|
|
+ ->first();
|
|
|
+ if(empty($customer)) return [false,'项目节点任务不存在或已被删除'];
|
|
|
+ $customer = $customer->toArray();
|
|
|
+ if(empty($data['data'])) return [false, '任务进展明细不能为空'];
|
|
|
+
|
|
|
+ $empDisplayMap = Employee::whereIn('id', array_unique(array_column($data['data'],'data_id')))
|
|
|
+ ->get(['id', 'code', 'title'])
|
|
|
+ ->mapWithKeys(function($item){
|
|
|
+ return [$item->id => "[{$item->code}]{$item->title}"];
|
|
|
+ })->toArray();
|
|
|
+
|
|
|
+ foreach ($data['data'] as $key => $value){
|
|
|
+ $line = $key + 1;
|
|
|
+ $t = "第" . $line . "行";
|
|
|
+ if(empty($value['data_id'])) return [false, '人员ID不能为空'];
|
|
|
+ $empId = $value['data_id'] ?? 0;
|
|
|
+ $empName = $empDisplayMap[$empId] ?? "ID:{$empId}";
|
|
|
+ if(empty($data['order_time'])) return [false, '提交日期不能为空'];
|
|
|
+ $order_time = $this->changeDateToDate($data['order_time']);
|
|
|
+ if($order_time > $customer['end_time'] || $order_time < $customer['start_time']) return [false, $t . "提交日期必须在任务周期内"];
|
|
|
+ $data['data'][$key]['order_time'] = $order_time;
|
|
|
+
|
|
|
+ // 校验数字有效性
|
|
|
+ $res = $this->checkNumber($value['start_time_hour'], 0, 'non-negative');
|
|
|
+ if(!$res['valid']) return [false, $t . "人员{$empName}开始点:" . $res['error']];
|
|
|
+ if($value['start_time_hour'] > 23) return [false, false, $t . "人员{$empName}开始点不合法"];
|
|
|
+ $res = $this->checkNumber($value['start_time_min'], 0, 'non-negative');
|
|
|
+ if(!$res['valid']) return [false, $t ."人员{$empName}开始分:" . $res['error']];
|
|
|
+ if($value['start_time_min'] > 60) return [false, false, $t . "人员{$empName}开始点不合法"];
|
|
|
+ $res = $this->checkNumber($value['end_time_hour'], 0, 'non-negative');
|
|
|
+ if(!$res['valid']) return [false, $t ."人员{$empName}结束点:" . $res['error']];
|
|
|
+ if($value['end_time_hour'] > 24) return [false, false, $t . "人员{$empName}结束点不合法"];
|
|
|
+ $res = $this->checkNumber($value['end_time_min'], 0, 'non-negative');
|
|
|
+ if(!$res['valid']) return [false, $t ."人员{$empName}结束分:" . $res['error']];
|
|
|
+ if($value['end_time_min'] > 60) return [false, false, $t . "人员{$empName}结束分不合法"];
|
|
|
+
|
|
|
+ $currentStart = $value['start_time_hour'] * 60 + $value['start_time_min'];
|
|
|
+ $currentEnd = $value['end_time_hour'] * 60 + $value['end_time_min'];
|
|
|
+
|
|
|
+ if ($currentStart >= $currentEnd) {
|
|
|
+ return [false, $t . "人员{$empName}:开始时间必须早于结束时间"];
|
|
|
+ }
|
|
|
+
|
|
|
+ // --- 新增:总分钟数校验 ---
|
|
|
+ $calculatedTotal = $currentEnd - $currentStart;
|
|
|
+ if (!isset($value['total_work_min']) || intval($value['total_work_min']) !== $calculatedTotal) {
|
|
|
+ return [false, $t . "人员{$empName}:工时计算有误,应为 {$calculatedTotal} 分钟"];
|
|
|
+ }
|
|
|
+
|
|
|
+ // --- 3. 内部重叠校验(防止一次提交多行重复) ---
|
|
|
+ if (isset($internalOverlap[$empId])) {
|
|
|
+ foreach ($internalOverlap[$empId] as $period) {
|
|
|
+ if ($currentStart < $period['e'] && $period['s'] < $currentEnd) {
|
|
|
+ return [false, "人员{$empName}在本次提交的多行明细中时间段重叠"];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ $internalOverlap[$empId][] = ['s' => $currentStart, 'e' => $currentEnd];
|
|
|
+
|
|
|
+ if(!isset($value['content'])) return [false, '工作内容字段不存在'];
|
|
|
+
|
|
|
+ $data['data'][$key]['item_id'] = $customer['item_id'];
|
|
|
+ $data['data'][$key]['item_node_id'] = $customer['item_node_id'];
|
|
|
+ $data['data'][$key]['item_node_mission_id'] = $customer['id'];
|
|
|
+ $data['data'][$key]['top_depart_id'] = $user['top_depart_id'];
|
|
|
+ $data['data'][$key]['crt_id'] = $user['id'];
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ DB::beginTransaction();
|
|
|
+ $time = time();
|
|
|
+
|
|
|
+ ItemNodeMissionContent::where('item_node_mission_id', $data['id'])->where('del_time',0)->update(['del_time' => $time]);
|
|
|
+
|
|
|
+ ItemNodeMissionContent::insert($data['data']);
|
|
|
+
|
|
|
+ DB::commit();
|
|
|
+ }catch (\Exception $exception){
|
|
|
+ DB::rollBack();
|
|
|
+ return [false,$exception->getMessage()];
|
|
|
+ }
|
|
|
+
|
|
|
+ return [true, ''];
|
|
|
+ }
|
|
|
+
|
|
|
+ public function itemNodeMissionUpdateProgress($data, $user){
|
|
|
+ if(empty($data['id'])) return [false, 'ID不能为空'];
|
|
|
+ if(empty($data['progress'])) return [false, '任务进展不能为空'];
|
|
|
+ $res = $this->checkNumber($data['progress'],0,'positive');
|
|
|
+ if (! $res['valid']) return [false, "任务进展:" . $res['error']];
|
|
|
+ if($data['progress'] > 100) return [false, '任务进展不能超过100'];
|
|
|
+
|
|
|
+ ItemNodeMission::where('id', $data['id'])->update(['progress' => $data['progress']]);
|
|
|
+
|
|
|
+ return [true, ''];
|
|
|
+ }
|
|
|
+
|
|
|
+ public function itemNodeMissionDetailBoard($data, $user){
|
|
|
+ list($status, $msg) = $this->itemNodeMissionDetail($data, $user);
|
|
|
+ if(! $status) return [false, $msg];
|
|
|
+ $customer = $msg;
|
|
|
+
|
|
|
+ //任务进展信息
|
|
|
+ $customer['mission_progress'] = $this->itemMissionProgressBoard($data, $user);
|
|
|
+
|
|
|
+ //文件归档
|
|
|
+ $customer['file_list'] = $this->getMissionProgressFile($data, $user, $customer);
|
|
|
+
|
|
|
+ return [true, $customer];
|
|
|
+ }
|
|
|
+
|
|
|
+ public function itemMissionProgressBoard($data,$user){
|
|
|
+ $list = ItemNodeMissionContent::where('del_time',0)
|
|
|
+ ->where('item_node_mission_id', $data['id'])
|
|
|
+ ->select('*')
|
|
|
+ ->get()->toArray();
|
|
|
+
|
|
|
+ $emp = (new EmployeeService())->getEmployeeMap(array_unique(array_merge_recursive(array_column($list,'data_id'), array_column($list,'crt_id'))));
|
|
|
+ foreach ($list as $key => $value){
|
|
|
+ $list[$key]['order_time'] = $value['order_time'] ? date('Y-m-d',$value['order_time']) : '';
|
|
|
+ $list[$key]['crt_time'] = $value['crt_time'] ? date('Y-m-d H:i:s',$value['crt_time']) : '';
|
|
|
+ $list[$key]['crt_name'] = $emp[$value['crt_id']] ?? '';
|
|
|
+ $list[$key]['data_name'] = $emp[$value['data_id']] ?? '';
|
|
|
+ }
|
|
|
+
|
|
|
+ return $list;
|
|
|
+ }
|
|
|
+
|
|
|
+ public function getMissionProgressFile($data, $user, $item){
|
|
|
+ $file = ItemFile::where('del_time',0)
|
|
|
+ ->where('item_node_mission_id', $data['id'])
|
|
|
+ ->get()->toArray();
|
|
|
+
|
|
|
+ $employee_id = array_unique(array_merge_recursive(array_column($file,'crt_id'), array_column($item['custom_fields'],'crt_id')));
|
|
|
+ $map = (new EmployeeService())->getEmployeeMap($employee_id);
|
|
|
+
|
|
|
+ $return = [];
|
|
|
+ if(! empty($item['custom_fields'])){
|
|
|
+ foreach ($item['custom_fields'] as $value){
|
|
|
+ if($value['field_type'] == CustomFieldValue::type_two){
|
|
|
+ $return[] = [
|
|
|
+ 'id' => $value['id'],
|
|
|
+ 'url' => $value['field_value'],
|
|
|
+ 'name' => $value['field_name'],
|
|
|
+ 'show_url' => $value['field_value_show'],
|
|
|
+ 'type_name' => '任务',
|
|
|
+ 'type_name_2' => CustomFieldValue::type[CustomFieldValue::type_two],
|
|
|
+ 'type' => 'custom_fields',
|
|
|
+ 'from' => ItemFile::type_two,
|
|
|
+ 'crt_name' => $map[$value['crt_id']],
|
|
|
+ 'crt_time' => date("Y-m-d", $value['crt_time']),
|
|
|
+ 'crt_id' => $value['crt_id'],
|
|
|
+ 'is_delivery' => $value['is_delivery'],
|
|
|
+ ];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if(! empty($file)){
|
|
|
+ $fileUploadService = new FileUploadService();
|
|
|
+ foreach ($file as $value){
|
|
|
+ $return[] = [
|
|
|
+ 'id' => $value['id'],
|
|
|
+ 'url' => $value['url'],
|
|
|
+ 'name' => $value['name'],
|
|
|
+ 'show_url' => $fileUploadService->getFileShow($value['url']),
|
|
|
+ 'type_name' => ItemFile::from[$value['from']],
|
|
|
+ 'type_name_2' => ItemFile::type[$value['type']],
|
|
|
+ 'type' => 'item_file',
|
|
|
+ 'from' => $value['from'],
|
|
|
+ 'crt_name' => $map[$value['crt_id']],
|
|
|
+ 'crt_time' => date("Y-m-d", $value['crt_time']),
|
|
|
+ 'crt_id' => $value['crt_id'],
|
|
|
+ 'is_delivery' => $value['is_delivery'],
|
|
|
+ ];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return $return;
|
|
|
+ }
|
|
|
+
|
|
|
public function itemNodeMissionCommon($data,$user, $field = []){
|
|
|
if(empty($field)) $field = ItemNodeMission::$field;
|
|
|
|
|
|
@@ -1644,11 +1835,16 @@ class ItemService extends Service
|
|
|
|
|
|
public function itemNodeMissionRule(&$data, $user, $is_add = true){
|
|
|
$data['top_depart_id'] = $user['top_depart_id'];
|
|
|
+ if(empty($data['item_node_id']) && empty($data['parent_item_node_mission_id'])) return [false, '节点与父级任务不能同时为空'];
|
|
|
if(empty($data['item_node_id'])) return [false, '项目节点ID不能为空'];
|
|
|
$item = ItemNode::where('id', $data['item_node_id'])->where('del_time',0)->first();
|
|
|
if(empty($item)) return [false, '项目节点不存在或已被删除'];
|
|
|
$item = $item->toArray();
|
|
|
$data['item_id'] = $item['item_id'];
|
|
|
+ if(! empty($data['parent_item_node_mission_id'])) {
|
|
|
+ $bool = ItemNodeMission::where('id', $data['parent_item_node_mission_id'])->where('del_time',0)->exists();
|
|
|
+ if(! $bool) return [false, '父任务不存在或已被删除'];
|
|
|
+ }
|
|
|
if(empty($data['title'])) return [false, '任务名称不能为空'];
|
|
|
if(! empty($data['start_time'])) $data['start_time'] = $this->changeDateToDate($data['start_time']);
|
|
|
if(! empty($data['end_time'])) $data['end_time'] = $this->changeDateToDate($data['end_time'],true);
|
|
|
@@ -1657,7 +1853,6 @@ class ItemService extends Service
|
|
|
$itemEndTime = $item['end_time'];
|
|
|
if (!empty($data['start_time'])) {
|
|
|
$inputStartTime = $data['start_time'];
|
|
|
-
|
|
|
if ($itemStartTime > 0 && $inputStartTime < $itemStartTime) {
|
|
|
return [false, '任务开始时间不能早于项目节点开始时间:' . date('Y-m-d', $itemStartTime)];
|
|
|
}
|
|
|
@@ -1668,7 +1863,6 @@ class ItemService extends Service
|
|
|
return [false, '任务结束时间不能晚于项目节点结束时间:' . date('Y-m-d', $itemEndTime)];
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
if(! empty($data['man_list'])) {
|
|
|
foreach ($data['man_list'] as $key => $value){
|
|
|
if(empty($value['type'])) return [false, '类型不能为空'];
|
|
|
@@ -1678,7 +1872,6 @@ class ItemService extends Service
|
|
|
list($status, $msg) = $this->checkArrayRepeat($data['man_list'],'data_id','人员');
|
|
|
if(! $status) return [false, $msg];
|
|
|
}
|
|
|
-
|
|
|
if(! empty($data['device_list'])) {
|
|
|
foreach ($data['device_list'] as $key => $value){
|
|
|
if(empty($value['type'])) return [false, '类型不能为空'];
|
|
|
@@ -1714,6 +1907,7 @@ class ItemService extends Service
|
|
|
|
|
|
$emp = (new EmployeeService())->getEmployeeMap(array_unique(array_merge_recursive(array_column($data['data'],'charge_id'), array_column($data['data'],'crt_id'))));
|
|
|
$tag = (new TagService())->getTagMap(array_unique(array_merge_recursive(array_column($data['data'],'priority_id'),array_column($data['data'],'mission_id'))));
|
|
|
+ $item_node_map = $this->getItemNodeMap(array_column($data['data'],'id'));
|
|
|
foreach ($data['data'] as $key => $value){
|
|
|
$data['data'][$key]['crt_time'] = $value['crt_time'] ? date('Y-m-d H:i:s',$value['crt_time']) : '';
|
|
|
$data['data'][$key]['start_time'] = $value['start_time'] ? date('Y-m-d',$value['start_time']) : '';
|
|
|
@@ -1727,8 +1921,18 @@ class ItemService extends Service
|
|
|
$node_tmp = $tag[$value['mission_id']] ?? [];
|
|
|
$data['data'][$key]['mission_title'] = $node_tmp['title'] ?? '';
|
|
|
$data['data'][$key]['mission_code'] = $node_tmp['code'] ?? '';
|
|
|
+ $data['data'][$key]['item_node_title'] = $item_node_map[$value['id']] ?? '';
|
|
|
}
|
|
|
|
|
|
return $data;
|
|
|
}
|
|
|
+
|
|
|
+ public function getItemNodeMap($item_node_mission_id){
|
|
|
+ if(! is_array($item_node_mission_id)) $item_node_mission_id = [$item_node_mission_id];
|
|
|
+ return ItemNodeMission::from('item_node_mission as a')
|
|
|
+ ->leftJoin('item_node as b','b.id','a.item_node_id')
|
|
|
+ ->whereIn('a.id', $item_node_mission_id)
|
|
|
+ ->pluck('b.title','a.id')
|
|
|
+ ->toArray();
|
|
|
+ }
|
|
|
}
|