ItemService.php 60 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504
  1. <?php
  2. namespace App\Service;
  3. use App\Jobs\ProcessOssTask;
  4. use App\Model\CustomFieldValue;
  5. use App\Model\Device;
  6. use App\Model\Employee;
  7. use App\Model\Item;
  8. use App\Model\ItemDetails;
  9. use App\Model\ItemEmployee;
  10. use App\Model\ItemFile;
  11. use App\Model\ItemNode;
  12. use App\Model\ItemNodeDetails;
  13. use App\Model\ItemNodeEmployee;
  14. use App\Model\ItemNodeMission;
  15. use App\Model\ItemNodeMissionDetails;
  16. use App\Model\ItemNodeMissionEmployee;
  17. use App\Model\SysOssTasks;
  18. use App\Model\Tag;
  19. use App\Model\SysMenu;
  20. use Illuminate\Support\Facades\DB;
  21. class ItemService extends Service
  22. {
  23. // 项目 任务 节点 都可以用的 文件上传 文件删除 更改交付物状态
  24. public function itemFileUpLoad($data,$user){
  25. // 1. 基础校验
  26. $from = $data['from'] ?? null;
  27. $fromMap = ItemFile::from;
  28. if (empty($from)) return [false, '上传来源类型不能为空'];
  29. if (!isset($fromMap[$from])) return [false, '上传来源类型错误'];
  30. $id = $data['id'] ?? null;
  31. if (empty($id)) return [false, '来源ID不能为空'];
  32. $modelMap = [
  33. ItemFile::from_one => Item::class,
  34. ItemFile::from_two => ItemNode::class,
  35. ItemFile::from_three => ItemNodeMission::class,
  36. ];
  37. $modelClass = $modelMap[$from] ?? "";
  38. $item = $modelClass::where('id', $id)->where('del_time', 0)->first();
  39. if (!$item) return [false, $fromMap[$from] . "不存在或已被删除"];
  40. $itemId = $item->item_id ?? $item->id;
  41. $itemNodeId = $item->item_node_id ?? ($from == ItemFile::from_one ? 0 : $item->id);
  42. $missionId = ($from != ItemFile::from_one && $from != ItemFile::type_two) ? $item->id : 0;
  43. $files = $data['file'] ?? [];
  44. if (empty($files)) return [false, '上传文件不能为空'];
  45. $time = time();
  46. $pendingTasks = [];
  47. foreach ($files as &$file) {
  48. if (empty($file['url']) || empty($file['type']) || empty($file['name'])) {
  49. return [false, '文件信息(URL/类型/名称)不完整'];
  50. }
  51. $file['top_depart_id'] = $user['top_depart_id'];
  52. $file['type'] = $from;
  53. $file['item_id'] = $itemId;
  54. $file['item_node_id'] = $itemNodeId;
  55. $file['item_node_mission_id'] = $missionId;
  56. $file['crt_time'] = $time;
  57. $pendingTasks[] = ['type' => SysOssTasks::type_two, 'url' => $file['url'], 'top_depart_id' => $user['top_depart_id'], 'crt_time' => $time];
  58. }
  59. unset($file);
  60. $data['file'] = $files;
  61. try {
  62. DB::beginTransaction();
  63. ItemFile::insert($data['file']);
  64. //触发 OSS 任务
  65. if (!empty($pendingTasks)) {
  66. SysOssTasks::insert($pendingTasks);
  67. ProcessOssTask::dispatch()->onQueue(SysOssTasks::job);
  68. }
  69. DB::commit();
  70. }catch (\Exception $exception){
  71. DB::rollBack();
  72. return [false,$exception->getMessage()];
  73. }
  74. return [true, ''];
  75. }
  76. public function itemFileUpDelete($data,$user){
  77. $fromMap = [
  78. 'custom_fields' => CustomFieldValue::class,
  79. 'item_file' => ItemFile::class,
  80. ];
  81. // 1. 基础校验
  82. $type = $data['type'] ?? null;
  83. if (empty($type)) return [false, '删除来源类型不能为空'];
  84. if (!isset($fromMap[$type])) return [false, '删除来源类型错误'];
  85. $id = $data['id'] ?? null;
  86. if (empty($id)) return [false, '来源ID不能为空'];
  87. $modelClass = $fromMap[$type] ?? "";
  88. $item = $modelClass::where('id', $id)->where('del_time', 0)->first();
  89. if (! $item) return [false, "文件不存在或已被删除"];
  90. try {
  91. DB::beginTransaction();
  92. $time = time();
  93. if($type == 'custom_fields'){
  94. if(empty($item->field_value)) return [false, '文件为空'];
  95. $pendingTasks[] = ['type' => SysOssTasks::type_one, 'url' => $item->field_value, 'top_depart_id' => $user['top_depart_id'], 'crt_time' => $time];
  96. $item->update([
  97. 'field_value' => '',
  98. 'field_name' => ''
  99. ]);
  100. }else{
  101. if(empty($item->url)) return [false, '文件为空'];
  102. $pendingTasks[] = ['type' => SysOssTasks::type_one, 'url' => $item->url, 'top_depart_id' => $user['top_depart_id'], 'crt_time' => $time];
  103. $item->update(['del_time' => $time]);
  104. }
  105. //触发 OSS 任务
  106. if (! empty($pendingTasks)) {
  107. SysOssTasks::insert($pendingTasks);
  108. ProcessOssTask::dispatch()->onQueue(SysOssTasks::job);
  109. }
  110. DB::commit();
  111. }catch (\Exception $exception){
  112. DB::rollBack();
  113. return [false,$exception->getMessage()];
  114. }
  115. return [true, ''];
  116. }
  117. public function itemFileIsDelivery($data, $user)
  118. {
  119. $typeMap = [
  120. 1 => '标记为交付物',
  121. 2 => '解除交付物',
  122. ];
  123. $fromMap = [
  124. 'custom_fields' => CustomFieldValue::class,
  125. 'item_file' => ItemFile::class,
  126. ];
  127. if (empty($data['opt_type']) || !isset($typeMap[$data['opt_type']])) return [false, '操作标识错误'];
  128. if (empty($data['data']) || !is_array($data['data'])) return [false, '文件数据不能为空'];
  129. // 状态值映射
  130. $statusValue = ($data['opt_type'] == 1) ? 1 : 0;
  131. $idsByType = [
  132. 'custom_fields' => [],
  133. 'item_file' => [],
  134. ];
  135. foreach ($data['data'] as $value) {
  136. if (empty($value['id'])) return [false, '文件ID不能为空'];
  137. if (empty($value['type']) || !isset($fromMap[$value['type']])) return [false, '文件类型错误'];
  138. $idsByType[$value['type']][] = $value['id'];
  139. }
  140. try {
  141. DB::beginTransaction();
  142. foreach ($idsByType as $type => $ids) {
  143. if (!empty($ids)) {
  144. $modelClass = $fromMap[$type];
  145. $modelClass::whereIn('id', $ids)->update([
  146. 'is_delivery' => $statusValue,
  147. ]);
  148. }
  149. }
  150. DB::commit();
  151. } catch (\Exception $exception) {
  152. DB::rollBack();
  153. return [false, $exception->getMessage()];
  154. }
  155. return [true, ''];
  156. }
  157. // 项目 任务 节点 都可以用的 文件上传 文件删除 更改交付物状态
  158. public function itemEdit($data,$user){
  159. list($status,$msg) = $this->itemRule($data, $user, false);
  160. if(!$status) return [$status,$msg];
  161. try {
  162. DB::beginTransaction();
  163. $model = Item::where('id', $data['id'])->first();
  164. $old_employee_id = $model->charge_id;
  165. $tableName = $model->getTable();
  166. $model->code = $data['code'] ?? '';
  167. $model->title = $data['title'] ?? '';
  168. $model->mark = $data['mark'] ?? "";
  169. $model->start_time = $data['start_time'] ?? 0;
  170. $model->end_time = $data['end_time'] ?? 0;
  171. $model->state = $data['state'] ?? 0;
  172. $model->budget = $data['budget'] ?? 0;
  173. $model->charge_id = $data['charge_id'] ?? 0;
  174. $model->field = $data['field'] ?? "";
  175. $model->item_attribute = $data['item_attribute'] ?? 0;
  176. //项目管理的字段
  177. if($user['select_tree_type'] == SysMenu::tree_type_one){
  178. $model->is_review_required = $data['is_review_required'] ?? 0;
  179. $model->review_id = $data['review_id'] ?? 0;
  180. $model->priority_id = $data['priority_id'] ?? 0;
  181. }
  182. $model->save();
  183. $time = time();
  184. // 人员项目表
  185. $this->saveEmployee($data['id'], $time, $data, $user, $old_employee_id);
  186. ItemDetails::where('del_time',0)
  187. ->where('item_id', $model->id)
  188. ->update(['del_time' => $time]);
  189. $this->saveDetail($model->id, $time, $data);
  190. list($status, $msg) = CustomFieldSettingService::syncCustomFieldData($model->id, $tableName, $data, $user);
  191. if (! $status) {
  192. DB::rollBack();
  193. return [false, $msg];
  194. }
  195. DB::commit();
  196. }catch (\Exception $exception){
  197. DB::rollBack();
  198. return [false,$exception->getMessage()];
  199. }
  200. return [true, ''];
  201. }
  202. public function itemAdd($data,$user){
  203. list($status,$msg) = $this->itemRule($data, $user);
  204. if(!$status) return [$status,$msg];
  205. try {
  206. DB::beginTransaction();
  207. $model = new Item();
  208. $tableName = $model->getTable();
  209. $model->code = $data['code'] ?? '';
  210. $model->title = $data['title'] ?? '';
  211. $model->mark = $data['mark'] ?? "";
  212. $model->start_time = $data['start_time'] ?? 0;
  213. $model->end_time = $data['end_time'] ?? 0;
  214. $model->state = $data['state'] ?? 0;
  215. $model->budget = $data['budget'] ?? 0;
  216. $model->charge_id = $data['charge_id'] ?? 0;
  217. $model->field = $data['field'] ?? "";
  218. $model->item_attribute = $data['item_attribute'] ?? 0;
  219. $model->is_review_required = $data['is_review_required'] ?? 0;
  220. $model->review_id = $data['review_id'] ?? 0;
  221. $model->priority_id = $data['priority_id'] ?? 0;
  222. $model->crt_id = $user['id'];
  223. $model->top_depart_id = $data['top_depart_id'];
  224. $model->save();
  225. $time = time();
  226. $this->saveDetail($model->id, $time, $data);
  227. // 人员项目表
  228. $this->saveEmployee($model->id, $time, $data, $user);
  229. list($status, $msg) = CustomFieldSettingService::syncCustomFieldData($model->id, $tableName, $data, $user);
  230. if (!$status) {
  231. DB::rollBack();
  232. return [false, $msg];
  233. }
  234. DB::commit();
  235. }catch (\Exception $exception){
  236. DB::rollBack();
  237. return [false,$exception->getMessage()];
  238. }
  239. return [true, ''];
  240. }
  241. private function saveDetail($id, $time, $data){
  242. if(! empty($data['man_list'])){
  243. $unit = [];
  244. foreach ($data['man_list'] as $value){
  245. $unit[] = [
  246. 'item_id' => $id,
  247. 'type' => $value['type'],
  248. 'data_id' => $value['data_id'],
  249. 'crt_time' => $time,
  250. 'top_depart_id' => $value['top_depart_id'],
  251. ];
  252. }
  253. if(! empty($unit)) ItemDetails::insert($unit);
  254. }
  255. if(! empty($data['device_list'])){
  256. $receipt = [];
  257. foreach ($data['device_list'] as $value){
  258. $receipt[] = [
  259. 'item_id' => $id,
  260. 'type' => $value['type'],
  261. 'data_id' => $value['data_id'],
  262. 'crt_time' => $time,
  263. 'top_depart_id' => $value['top_depart_id'],
  264. ];
  265. }
  266. if(! empty($receipt)) ItemDetails::insert($receipt);
  267. }
  268. }
  269. private function saveEmployee($id, $time, $data, $user, $old_employee_id = 0){
  270. if($old_employee_id != $data['charge_id']){
  271. ItemEmployee::where('del_time',0)
  272. ->where('item_id', $id)
  273. ->where('data_id', $old_employee_id)
  274. ->delete();
  275. ItemEmployee::insert([
  276. 'item_id' => $id,
  277. 'data_id' => $data['charge_id'],
  278. 'top_depart_id' => $user['top_depart_id'],
  279. 'crt_time' => $time
  280. ]);
  281. }
  282. }
  283. private function getDetail($id){
  284. $data = ItemDetails::where('del_time',0)
  285. ->where('item_id', $id)
  286. ->get()->toArray();
  287. $id = $id2 = [];
  288. foreach ($data as $value){
  289. if($value['type'] == ItemDetails::type_one) {
  290. $id[] = $value['data_id'];
  291. }else{
  292. $id2[] = $value['data_id'];
  293. }
  294. }
  295. $map = Employee::whereIn('id', $id)->select('title','id','number')->get()->toArray();
  296. $map = array_column($map,null,'id');
  297. $map2 = Device::whereIn('id', $id2)->select('code','id','title')->get()->toArray();
  298. $map2 = array_column($map2,null,'id');
  299. $unit = $receipt = [];
  300. foreach ($data as $value){
  301. if($value['type'] == ItemDetails::type_one) {
  302. $tmp = $map[$value['data_id']] ?? [];
  303. $unit[] = [
  304. 'type' => $value['type'],
  305. 'data_id' => $value['data_id'],
  306. 'data_title' => $tmp['title'],
  307. 'data_code' => $tmp['number'],
  308. ];
  309. }else{
  310. $tmp = $map2[$value['data_id']] ?? [];
  311. $receipt[] = [
  312. 'type' => $value['type'],
  313. 'data_id' => $value['data_id'],
  314. 'data_title' => $tmp['title'] ?? "",
  315. 'data_code' => $tmp['code'] ?? "",
  316. ];
  317. }
  318. }
  319. return [
  320. 'man_list' => $unit,
  321. 'device_list' => $receipt,
  322. ];
  323. }
  324. public function getItemMap($ids){
  325. $ids = array_filter((array)$ids);
  326. if (empty($ids)) return [];
  327. return Item::whereIn('id', $ids)
  328. ->select('id', 'title', 'code')
  329. ->get()
  330. ->keyBy('id')
  331. ->toArray();
  332. }
  333. public function itemDel($data){
  334. if($this->isEmpty($data,'id')) return [false,'请选择数据!'];
  335. try {
  336. DB::beginTransaction();
  337. $time = time();
  338. Item::where('del_time',0)
  339. ->whereIn('id',$data['id'])
  340. ->update(['del_time' => $time]);
  341. ItemDetails::where('del_time',0)
  342. ->whereIn('item_id', $data['id'])
  343. ->update(['del_time' => $time]);
  344. DB::commit();
  345. }catch (\Exception $exception){
  346. DB::rollBack();
  347. return [false,$exception->getMessage()];
  348. }
  349. return [true, ''];
  350. }
  351. public function itemDetail($data, $user){
  352. if($this->isEmpty($data,'id')) return [false,'请选择数据!'];
  353. $customer = Item::where('del_time',0)
  354. ->withCustomData($user)
  355. ->where('id',$data['id'])
  356. ->first();
  357. if(empty($customer)) return [false,'项目不存在或已被删除'];
  358. $customer->getFormattedCustomFields();// 自定义数据附件处理
  359. $customer = $customer->toArray();
  360. $customer['start_time'] = ! empty($customer['start_time']) ? date("Y-m-d", $customer['start_time']) : "";
  361. $customer['end_time'] = ! empty($customer['end_time']) ? date("Y-m-d", $customer['end_time']) : "";
  362. $customer['crt_name'] = Employee::where('id',$customer['crt_id'])->value('title');
  363. $customer['charge_name'] = Employee::where('id',$customer['charge_id'])->value('title');
  364. $customer['crt_time'] = $customer['crt_time'] ? date("Y-m-d H:i:s",$customer['crt_time']): '';
  365. $customer['state_title'] = Item::State_Type[$customer['state']] ?? '';
  366. $customer['priority_title'] = Tag::where('id', $customer['priority_id'])->value('title') ?? "";
  367. $details = $this->getDetail($data['id']);
  368. $customer = array_merge($customer, $details);
  369. return [true, $customer];
  370. }
  371. public function itemDetailBoard($data, $user){
  372. list($status, $msg) = $this->itemDetail($data, $user);
  373. if(! $status) return [false, $msg];
  374. $customer = $msg;
  375. //节点信息
  376. $customer['node_list'] = $this->itemNodeBoard($data, $user);
  377. //文件归档
  378. $customer['file_list'] = $this->getNodeFile($data, $user, $customer);
  379. return [true, $customer];
  380. }
  381. public function itemNodeBoard($data,$user){
  382. $model = ItemNode::TopAndEmployeeClear($user,$data);
  383. $list = $model->where('del_time',0)
  384. ->where('item_id', $data['id'])
  385. ->select('*')
  386. ->orderby('upd_time', 'desc')
  387. ->orderby('id', 'desc')
  388. ->get()->toArray();
  389. $emp = (new EmployeeService())->getEmployeeMap(array_unique(array_merge_recursive(array_column($list,'charge_id'), array_column($list,'crt_id'))));
  390. $tag = (new TagService())->getTagMap(array_unique(array_merge_recursive(array_column($list,'priority_id'),array_column($list,'node_id'))));
  391. foreach ($list as $key => $value){
  392. $list[$key]['crt_time'] = $value['crt_time'] ? date('Y-m-d H:i:s',$value['crt_time']) : '';
  393. $list[$key]['start_time'] = $value['start_time'] ? date('Y-m-d',$value['start_time']) : '';
  394. $list[$key]['end_time'] = $value['end_time'] ? date('Y-m-d',$value['end_time']) : '';
  395. $list[$key]['crt_name'] = $emp[$value['crt_id']] ?? '';
  396. $list[$key]['charge_name'] = $emp[$value['charge_id']] ?? '';
  397. $list[$key]['state_title'] = ItemNode::State_Type[$value['state']] ?? "";
  398. $priority_tmp = $tag[$value['priority_id']] ?? [];
  399. $list[$key]['priority_title'] = $priority_tmp['title'] ?? '';
  400. $list[$key]['priority_code'] = $priority_tmp['code'] ?? '';
  401. $node_tmp = $tag[$value['node_id']] ?? [];
  402. $list[$key]['node_title'] = $node_tmp['title'] ?? '';
  403. $list[$key]['node_code'] = $node_tmp['code'] ?? '';
  404. $list[$key]['progress'] = rand(1, 100); //todo
  405. }
  406. return $list;
  407. }
  408. public function getNodeFile($data,$user, $item){
  409. $return = [];
  410. if(! empty($item['custom_fields'])){
  411. foreach ($item['custom_fields'] as $value){
  412. $return[] = [
  413. 'id' => $value['id'],
  414. 'url' => $value['field_value'],
  415. 'name' => $value['field_name'],
  416. 'show_url' => $value['field_value_show'],
  417. 'type_name' => '项目',
  418. 'type_name_2' => CustomFieldValue::type[CustomFieldValue::type_two],
  419. 'type' => 'custom_fields',
  420. ];
  421. }
  422. }
  423. $file = ItemFile::where('del_time',0)
  424. ->where('item_id', $data['id'])
  425. ->get()->toArray();
  426. if(! empty($file)){
  427. $fileUploadService = new FileUploadService();
  428. foreach ($file as $value){
  429. $return[] = [
  430. 'id' => $value['id'],
  431. 'url' => $value['url'],
  432. 'name' => $value['name'],
  433. 'show_url' => $fileUploadService->getFileShow($value['url']),
  434. 'type_name' => ItemFile::from[$value['from']],
  435. 'type_name_2' => ItemFile::type[$value['type']],
  436. 'type' => 'item_file',
  437. ];
  438. }
  439. }
  440. return $return;
  441. }
  442. public function itemCommon($data,$user, $field = []){
  443. if(empty($field)) $field = Item::$field;
  444. $model = Item::TopClear($user,$data);
  445. $model = $model->where('del_time',0)
  446. ->select($field)
  447. ->orderby('id', 'desc');
  448. if(! empty($data['title'])) $model->where('title', 'LIKE', '%'.$data['title'].'%');
  449. if(! empty($data['code'])) $model->where('code', 'LIKE', '%'.$data['code'].'%');
  450. if(! empty($data['id'])) $model->whereIn('id', $data['id']);
  451. if(! empty($data['state'])) $model->where('state', $data['state']);
  452. if(! empty($data['crt_time'][0]) && ! empty($data['crt_time'][1])) {
  453. $return = $this->changeDateToTimeStampAboutRange($data['crt_time']);
  454. $model->where('crt_time','>=',$return[0]);
  455. $model->where('crt_time','<=',$return[1]);
  456. }
  457. return $model;
  458. }
  459. public function itemCommon1($data,$user, $field = []){
  460. if(empty($field)) $field = Item::$field;
  461. $model = Item::TopAndEmployeeClear($user,$data);
  462. $model = $model->where('del_time',0)
  463. ->select($field)
  464. ->orderby('id', 'desc');
  465. if(! empty($data['title'])) $model->where('title', 'LIKE', '%'.$data['title'].'%');
  466. if(! empty($data['code'])) $model->where('code', 'LIKE', '%'.$data['code'].'%');
  467. if(! empty($data['id'])) $model->whereIn('id', $data['id']);
  468. if(! empty($data['state'])) $model->where('state', $data['state']);
  469. if(! empty($data['crt_time'][0]) && ! empty($data['crt_time'][1])) {
  470. $return = $this->changeDateToTimeStampAboutRange($data['crt_time']);
  471. $model->where('crt_time','>=',$return[0]);
  472. $model->where('crt_time','<=',$return[1]);
  473. }
  474. return $model;
  475. }
  476. public function itemList($data,$user){
  477. $select_tree_type = $user['select_tree_type'];
  478. if(empty($select_tree_type)){
  479. //工时
  480. $model = $this->itemCommon($data, $user);
  481. }else{
  482. //项目管理
  483. $model = $this->itemCommon1($data, $user);
  484. }
  485. $list = $this->limit($model,'',$data);
  486. $list = $this->fillData($list);
  487. return [true, $list];
  488. }
  489. public function itemRule(&$data, $user, $is_add = true){
  490. $data['top_depart_id'] = $user['top_depart_id'];
  491. if(empty($data['code'])) return [false, '项目编码不能为空'];
  492. if(empty($data['title'])) return [false, '项目名称不能为空'];
  493. if(! empty($data['start_time'])) $data['start_time'] = $this->changeDateToDate($data['start_time']);
  494. if(! empty($data['end_time'])) $data['end_time'] = $this->changeDateToDate($data['end_time'],true);
  495. $isMonthEnd = date('j', $data['end_time']) == date('t', $data['end_time']);
  496. if(! $isMonthEnd) return [false, '项目结束日期必须是当月最后一天'];
  497. if(empty($data['state'])) return [false, '项目状态不能为空'];
  498. if(! isset(Item::State_Type[$data['state']])) return [false, '项目状态不存在'];
  499. if(empty($data['man_list'])) return [false, '人员不能为空'];
  500. foreach ($data['man_list'] as $key => $value){
  501. if(empty($value['type'])) return [false, '类型不能为空'];
  502. if(empty($value['data_id'])) return [false, '人员不能为空'];
  503. $data['man_list'][$key]['top_depart_id'] = $data['top_depart_id'];
  504. }
  505. list($status, $msg) = $this->checkArrayRepeat($data['man_list'],'data_id','人员');
  506. if(! $status) return [false, $msg];
  507. if(empty($data['device_list'])) return [false, '设备不能为空'];
  508. if(isset($data['device_list'])){
  509. foreach ($data['device_list'] as $key => $value){
  510. if(empty($value['type'])) return [false, '类型不能为空'];
  511. if(empty($value['data_id'])) return [false, '设备ID不能为空'];
  512. $data['device_list'][$key]['top_depart_id'] = $data['top_depart_id'];
  513. }
  514. }
  515. list($status, $msg) = $this->checkArrayRepeat($data['device_list'],'data_id','设备');
  516. if(! $status) return [false, $msg];
  517. if(isset($data['budget'])){
  518. $res = $this->checkNumber($data['budget'],2,'non-negative');
  519. if(! $res['valid']) return [false,'预算:' . $res['error']];
  520. }
  521. if(! empty($data['item_attribute']) && ! isset(Item::Item_Attribute[$data['item_attribute']])) return [false, '项目属性不存在'];
  522. if($is_add){
  523. $bool = Item::where('code',$data['code'])
  524. ->where('top_depart_id', $data['top_depart_id'])
  525. ->where('del_time',0)
  526. ->exists();
  527. }else{
  528. if(empty($data['id'])) return [false,'ID不能为空'];
  529. $bool = Item::where('code',$data['code'])
  530. ->where('top_depart_id', $data['top_depart_id'])
  531. ->where('id','<>',$data['id'])
  532. ->where('del_time',0)
  533. ->exists();
  534. }
  535. if($bool) return [false, '项目编码已存在'];
  536. return [true, ''];
  537. }
  538. public function fillData($data){
  539. if(empty($data['data'])) return $data;
  540. $emp = (new EmployeeService())->getEmployeeMap(array_unique(array_merge_recursive(array_column($data['data'],'charge_id'), array_column($data['data'],'crt_id'))));
  541. foreach ($data['data'] as $key => $value){
  542. $data['data'][$key]['crt_time'] = $value['crt_time'] ? date('Y-m-d H:i:s',$value['crt_time']) : '';
  543. $data['data'][$key]['start_time'] = $value['start_time'] ? date('Y-m-d',$value['start_time']) : '';
  544. $data['data'][$key]['end_time'] = $value['end_time'] ? date('Y-m-d',$value['end_time']) : '';
  545. $data['data'][$key]['crt_name'] = $emp[$value['crt_id']] ?? '';
  546. $data['data'][$key]['charge_name'] = $emp[$value['charge_id']] ?? '';
  547. $data['data'][$key]['state_title'] = Item::State_Type[$value['state']] ?? "";
  548. }
  549. return $data;
  550. }
  551. /**
  552. * 填充项目导出数据(主表与明细平铺)
  553. */
  554. public function fillDataForExport($data, $column, $user, &$return)
  555. {
  556. if (empty($data)) return;
  557. $dataArray = is_array($data) ? $data : $data->toArray();
  558. $mainIds = array_column($dataArray, 'id');
  559. // 1. 获取详情映射 [item_id => [ [type_title=>..., code_2=>..., title=>...], ... ]]
  560. $detailsMap = $this->getDetailsMap($mainIds, $user);
  561. // 2. 获取主表状态映射
  562. $stateMap = \App\Model\Item::State_Type;
  563. $attrMap = \App\Model\Item::Item_Attribute;
  564. $empMap = Employee::whereIn('id', array_unique(array_column($dataArray,'charge_id')))->get()->keyBy('id');
  565. foreach ($dataArray as $main) {
  566. $itemId = $main['id'];
  567. $details = $detailsMap[$itemId] ?? [];
  568. // 3. 提取并格式化主表信息
  569. $mainInfo = $main;
  570. $mainInfo['state_title'] = $stateMap[$main['state'] ?? ''] ?? '';
  571. $mainInfo['item_attribute_title'] = $attrMap[$main['item_attribute'] ?? ''] ?? '';
  572. $tmpEmp = $empMap[$main['charge_id']] ?? null;
  573. $mainInfo['charge_number'] = $tmpEmp ? $tmpEmp->number : '';
  574. $mainInfo['charge_name'] = $tmpEmp ? $tmpEmp->title : '';
  575. // 日期格式化
  576. $mainInfo['start_time'] = !empty($main['start_time']) ? date('Y-m-d', $main['start_time']) : '';
  577. $mainInfo['end_time'] = !empty($main['end_time']) ? date('Y-m-d', $main['end_time']) : '';
  578. if (empty($details)) {
  579. // 如果单据没有明细,保底出一行
  580. $tempRow = [];
  581. foreach ($column as $col) {
  582. $tempRow[] = $mainInfo[$col] ?? '';
  583. }
  584. $return[] = $tempRow;
  585. } else {
  586. // 4. 核心平铺逻辑:每一行明细都带上主表信息
  587. foreach ($details as $sub) {
  588. // 合并主表数据和详情数据(sub 中包含 type_title, code_2, title 等)
  589. $fullRowData = array_merge($mainInfo, $sub);
  590. $tempRow = [];
  591. foreach ($column as $col) {
  592. $tempRow[] = $fullRowData[$col] ?? '';
  593. }
  594. $return[] = $tempRow;
  595. }
  596. }
  597. }
  598. }
  599. /**
  600. * 获取明细聚合映射表
  601. */
  602. public function getDetailsMap($mainIds, $user)
  603. {
  604. $details = ItemDetails::where('del_time', 0)
  605. ->whereIn('item_id', $mainIds)
  606. ->where('top_depart_id', $user['top_depart_id'])
  607. ->get();
  608. if ($details->isEmpty()) return [];
  609. // 1. 批量提取关联 ID
  610. $empIds = $details->where('type', ItemDetails::type_one)->pluck('data_id')->unique();
  611. $devIds = $details->where('type', ItemDetails::type_two)->pluck('data_id')->unique();
  612. // 2. 批量获取档案 Map
  613. $empMap = Employee::whereIn('id', $empIds)->get()->keyBy('id');
  614. $devMap = Device::whereIn('id', $devIds)->get()->keyBy('id');
  615. $typeNames = ItemDetails::$type_name;
  616. $res = [];
  617. foreach ($details as $item) {
  618. $detailRow = [];
  619. $detailRow['type_title'] = $typeNames[$item->type] ?? '';
  620. // 根据类型处理影子列 code_2 和 名称 title
  621. if ($item->type == ItemDetails::type_one) {
  622. $emp = $empMap[$item->data_id] ?? null;
  623. $detailRow['code_2'] = $emp ? $emp->number : '';
  624. $detailRow['title_2'] = $emp ? $emp->title : '';
  625. } else {
  626. $dev = $devMap[$item->data_id] ?? null;
  627. $detailRow['code_2'] = $dev ? $dev->code : '';
  628. $detailRow['title_2'] = $dev ? $dev->title : '';
  629. }
  630. // 归档到对应的主表 ID 下
  631. $res[$item->item_id][] = $detailRow;
  632. }
  633. return $res;
  634. }
  635. //项目节点
  636. public function itemNodeEdit($data,$user){
  637. list($status,$msg) = $this->itemNodeRule($data, $user, false);
  638. if(!$status) return [$status,$msg];
  639. try {
  640. DB::beginTransaction();
  641. $model = ItemNode::where('id', $data['id'])->first();
  642. $old_employee_id = $model->charge_id;
  643. $tableName = $model->getTable();
  644. $model->title = $data['title'] ?? '';
  645. $model->mark = $data['mark'] ?? "";
  646. $model->start_time = $data['start_time'] ?? 0;
  647. $model->end_time = $data['end_time'] ?? 0;
  648. $model->is_delivery_required = $data['is_delivery_required'] ?? 0;
  649. $model->entrust_type = $data['entrust_type'] ?? 0;
  650. $model->charge_id = $data['charge_id'] ?? 0;
  651. $model->node_id = $data['node_id'] ?? 0;
  652. $model->node_weight = $data['node_weight'] ?? 0;
  653. $model->is_review_required = $data['is_review_required'] ?? 0;
  654. $model->review_id = $data['review_id'] ?? 0;
  655. $model->priority_id = $data['priority_id'] ?? 0;
  656. $model->save();
  657. $time = time();
  658. ItemNodeDetails::where('del_time',0)
  659. ->where('item_node_id', $model->id)
  660. ->update(['del_time' => $time]);
  661. $this->saveNodeDetail($model->id, $time, $data);
  662. // 人员项目节点表
  663. $this->saveNodeEmployee($model->id, $time, $data, $user, $old_employee_id);
  664. list($status, $msg) = CustomFieldSettingService::syncCustomFieldData($model->id, $tableName, $data, $user);
  665. if (! $status) {
  666. DB::rollBack();
  667. return [false, $msg];
  668. }
  669. DB::commit();
  670. }catch (\Exception $exception){
  671. DB::rollBack();
  672. return [false,$exception->getMessage()];
  673. }
  674. return [true, ''];
  675. }
  676. public function itemNodeAdd($data,$user){
  677. list($status,$msg) = $this->itemNodeRule($data, $user);
  678. if(!$status) return [$status,$msg];
  679. try {
  680. DB::beginTransaction();
  681. $model = new ItemNode();
  682. $model->item_id = $data['item_id'] ?? 0;
  683. $tableName = $model->getTable();
  684. $model->code = $this->generateBillNo([
  685. 'top_depart_id' => $user['top_depart_id'],
  686. 'type' => ItemNode::Order_type,
  687. 'period' => date("Ym", time())
  688. ]);
  689. $model->title = $data['title'] ?? '';
  690. $model->mark = $data['mark'] ?? "";
  691. $model->start_time = $data['start_time'] ?? 0;
  692. $model->end_time = $data['end_time'] ?? 0;
  693. $model->is_delivery_required = $data['is_delivery_required'] ?? 0;
  694. $model->entrust_type = $data['entrust_type'] ?? 0;
  695. $model->charge_id = $data['charge_id'] ?? 0;
  696. $model->node_id = $data['node_id'] ?? 0;
  697. $model->node_weight = $data['node_weight'] ?? 0;
  698. $model->is_review_required = $data['is_review_required'] ?? 0;
  699. $model->review_id = $data['review_id'] ?? 0;
  700. $model->priority_id = $data['priority_id'] ?? 0;
  701. $model->crt_id = $user['id'];
  702. $model->top_depart_id = $data['top_depart_id'];
  703. $model->save();
  704. $time = time();
  705. $this->saveNodeDetail($model->id, $time, $data);
  706. // 人员项目节点表
  707. $this->saveNodeEmployee($model->id, $time, $data, $user);
  708. list($status, $msg) = CustomFieldSettingService::syncCustomFieldData($model->id, $tableName, $data, $user);
  709. if (!$status) {
  710. DB::rollBack();
  711. return [false, $msg];
  712. }
  713. DB::commit();
  714. }catch (\Exception $exception){
  715. DB::rollBack();
  716. return [false,$exception->getMessage()];
  717. }
  718. return [true, ''];
  719. }
  720. private function saveNodeEmployee($id, $time, $data, $user, $old_employee_id = 0){
  721. if($old_employee_id != $data['charge_id']){
  722. ItemNodeEmployee::where('del_time',0)
  723. ->where('item_node_id', $id)
  724. ->where('data_id', $old_employee_id)
  725. ->delete();
  726. ItemNodeEmployee::insert([
  727. 'item_node_id' => $id,
  728. 'item_id' => $data['item_id'],
  729. 'data_id' => $data['charge_id'],
  730. 'top_depart_id' => $user['top_depart_id'],
  731. 'crt_time' => $time
  732. ]);
  733. }
  734. }
  735. private function saveNodeDetail($id, $time, $data){
  736. if(! empty($data['man_list'])){
  737. $unit = [];
  738. foreach ($data['man_list'] as $value){
  739. $unit[] = [
  740. 'item_id' => $data['item_id'],
  741. 'item_node_id' => $id,
  742. 'type' => $value['type'],
  743. 'data_id' => $value['data_id'],
  744. 'crt_time' => $time,
  745. 'top_depart_id' => $value['top_depart_id'],
  746. ];
  747. }
  748. if(! empty($unit)) ItemNodeDetails::insert($unit);
  749. }
  750. if(! empty($data['device_list'])){
  751. $receipt = [];
  752. foreach ($data['device_list'] as $value){
  753. $receipt[] = [
  754. 'item_id' => $data['item_id'],
  755. 'item_node_id' => $id,
  756. 'type' => $value['type'],
  757. 'data_id' => $value['data_id'],
  758. 'crt_time' => $time,
  759. 'top_depart_id' => $value['top_depart_id'],
  760. ];
  761. }
  762. if(! empty($receipt)) ItemNodeDetails::insert($receipt);
  763. }
  764. }
  765. private function getNodeDetail($id){
  766. $data = ItemNodeDetails::where('del_time',0)
  767. ->where('item_node_id', $id)
  768. ->get()->toArray();
  769. $id = $id2 = [];
  770. foreach ($data as $value){
  771. if($value['type'] == ItemNodeDetails::type_one) {
  772. $id[] = $value['data_id'];
  773. }else{
  774. $id2[] = $value['data_id'];
  775. }
  776. }
  777. $map = Employee::whereIn('id', $id)->select('title','id','number')->get()->toArray();
  778. $map = array_column($map,null,'id');
  779. $map2 = Device::whereIn('id', $id2)->select('code','id','title')->get()->toArray();
  780. $map2 = array_column($map2,null,'id');
  781. $unit = $receipt = [];
  782. foreach ($data as $value){
  783. if($value['type'] == ItemNodeDetails::type_one) {
  784. $tmp = $map[$value['data_id']] ?? [];
  785. $unit[] = [
  786. 'type' => $value['type'],
  787. 'data_id' => $value['data_id'],
  788. 'data_title' => $tmp['title'],
  789. 'data_code' => $tmp['number'],
  790. ];
  791. }else{
  792. $tmp = $map2[$value['data_id']] ?? [];
  793. $receipt[] = [
  794. 'type' => $value['type'],
  795. 'data_id' => $value['data_id'],
  796. 'data_title' => $tmp['title'] ?? "",
  797. 'data_code' => $tmp['code'] ?? "",
  798. ];
  799. }
  800. }
  801. return [
  802. 'man_list' => $unit,
  803. 'device_list' => $receipt,
  804. ];
  805. }
  806. public function itemNodeDel($data){
  807. if($this->isEmpty($data,'id')) return [false,'请选择数据!'];
  808. try {
  809. DB::beginTransaction();
  810. $time = time();
  811. ItemNode::where('del_time',0)
  812. ->whereIn('id',$data['id'])
  813. ->update(['del_time' => $time]);
  814. ItemNodeDetails::where('del_time',0)
  815. ->whereIn('item_node_id', $data['id'])
  816. ->update(['del_time' => $time]);
  817. DB::commit();
  818. }catch (\Exception $exception){
  819. DB::rollBack();
  820. return [false,$exception->getMessage()];
  821. }
  822. return [true, ''];
  823. }
  824. public function itemNodeDetail($data, $user){
  825. if($this->isEmpty($data,'id')) return [false,'请选择数据!'];
  826. $customer = ItemNode::where('del_time',0)
  827. ->withCustomData($user)
  828. ->where('id',$data['id'])
  829. ->first();
  830. if(empty($customer)) return [false,'项目节点不存在或已被删除'];
  831. $customer->getFormattedCustomFields();// 自定义数据附件处理
  832. $customer = $customer->toArray();
  833. $customer['start_time'] = ! empty($customer['start_time']) ? date("Y-m-d", $customer['start_time']) : "";
  834. $customer['end_time'] = ! empty($customer['end_time']) ? date("Y-m-d", $customer['end_time']) : "";
  835. $customer['crt_name'] = Employee::where('id',$customer['crt_id'])->value('title');
  836. $customer['charge_name'] = Employee::where('id',$customer['charge_id'])->value('title');
  837. $customer['crt_time'] = $customer['crt_time'] ? date("Y-m-d H:i:s",$customer['crt_time']): '';
  838. $customer['state_title'] = ItemNode::State_Type[$customer['state']] ?? '';
  839. $tag = (new TagService())->getTagMap(array_unique([$customer['priority_id'], $customer['node_id'] ]));
  840. $priority_tmp = $tag[$customer['priority_id']] ?? [];
  841. $customer['priority_title'] = $priority_tmp['title'] ?? '';
  842. $customer['priority_code'] = $priority_tmp['code'] ?? '';
  843. $node_tmp = $tag[$customer['node_id']] ?? [];
  844. $customer['node_title'] = $node_tmp['title'] ?? '';
  845. $customer['node_code'] = $node_tmp['code'] ?? '';
  846. $details = $this->getNodeDetail($data['id']);
  847. $customer = array_merge($customer, $details);
  848. return [true, $customer];
  849. }
  850. public function itemNodeCommon($data,$user, $field = []){
  851. if(empty($field)) $field = ItemNode::$field;
  852. $model = ItemNode::TopAndEmployeeClear($user,$data);
  853. $model = $model->where('del_time',0)
  854. ->select($field)
  855. ->orderby('id', 'desc');
  856. if(! empty($data['title'])) $model->where('title', 'LIKE', '%'.$data['title'].'%');
  857. if(! empty($data['code'])) $model->where('code', 'LIKE', '%'.$data['code'].'%');
  858. if(! empty($data['id'])) $model->whereIn('id', $data['id']);
  859. if(isset($data['state'])) $model->where('state', $data['state']);
  860. if(! empty($data['crt_time'][0]) && ! empty($data['crt_time'][1])) {
  861. $return = $this->changeDateToTimeStampAboutRange($data['crt_time']);
  862. $model->where('crt_time','>=',$return[0]);
  863. $model->where('crt_time','<=',$return[1]);
  864. }
  865. return $model;
  866. }
  867. public function itemNodeList($data,$user){
  868. $model = $this->itemNodeCommon($data, $user);
  869. $list = $this->limit($model,'',$data);
  870. $list = $this->fillNodeData($list);
  871. return [true, $list];
  872. }
  873. public function itemNodeRule(&$data, $user, $is_add = true){
  874. $data['top_depart_id'] = $user['top_depart_id'];
  875. if(empty($data['item_id'])) return [false, '项目ID不能为空'];
  876. $item = Item::where('id', $data['item_id'])->where('del_time',0)->first();
  877. if(empty($item)) return [false, '项目不存在或已被删除'];
  878. $item = $item->toArray();
  879. if(empty($data['title'])) return [false, '节点名称不能为空'];
  880. if(! empty($data['start_time'])) $data['start_time'] = $this->changeDateToDate($data['start_time']);
  881. if(! empty($data['end_time'])) $data['end_time'] = $this->changeDateToDate($data['end_time'],true);
  882. $itemStartTime = $item['start_time'];
  883. $itemEndTime = $item['end_time'];
  884. if (!empty($data['start_time'])) {
  885. $inputStartTime = $data['start_time'];
  886. if ($itemStartTime > 0 && $inputStartTime < $itemStartTime) {
  887. return [false, '节点开始时间不能早于项目开始时间:' . date('Y-m-d', $itemStartTime)];
  888. }
  889. }
  890. if (!empty($data['end_time'])) {
  891. $inputEndTime = $data['end_time'];
  892. if ($itemEndTime > 0 && $inputEndTime > $itemEndTime) {
  893. return [false, '节点结束时间不能晚于项目结束时间:' . date('Y-m-d', $itemEndTime)];
  894. }
  895. }
  896. if(! empty($data['man_list'])) {
  897. foreach ($data['man_list'] as $key => $value){
  898. if(empty($value['type'])) return [false, '类型不能为空'];
  899. if(empty($value['data_id'])) return [false, '人员不能为空'];
  900. $data['man_list'][$key]['top_depart_id'] = $data['top_depart_id'];
  901. }
  902. list($status, $msg) = $this->checkArrayRepeat($data['man_list'],'data_id','人员');
  903. if(! $status) return [false, $msg];
  904. }
  905. if(! empty($data['device_list'])) {
  906. foreach ($data['device_list'] as $key => $value){
  907. if(empty($value['type'])) return [false, '类型不能为空'];
  908. if(empty($value['data_id'])) return [false, '设备ID不能为空'];
  909. $data['device_list'][$key]['top_depart_id'] = $data['top_depart_id'];
  910. }
  911. list($status, $msg) = $this->checkArrayRepeat($data['device_list'],'data_id','设备');
  912. if(! $status) return [false, $msg];
  913. }
  914. if($is_add){
  915. $bool = ItemNode::where('item_id',$data['item_id'])
  916. ->where('top_depart_id', $data['top_depart_id'])
  917. ->where('title', $data['title'])
  918. ->where('del_time',0)
  919. ->exists();
  920. }else{
  921. if(empty($data['id'])) return [false,'ID不能为空'];
  922. $bool = ItemNode::where('title', $data['title'])
  923. ->where('item_id',$data['item_id'])
  924. ->where('top_depart_id', $data['top_depart_id'])
  925. ->where('id','<>',$data['id'])
  926. ->where('del_time',0)
  927. ->exists();
  928. }
  929. if($bool) return [false, '该项目下节点名称已存在'];
  930. return [true, ''];
  931. }
  932. public function fillNodeData($data){
  933. if(empty($data['data'])) return $data;
  934. $emp = (new EmployeeService())->getEmployeeMap(array_unique(array_merge_recursive(array_column($data['data'],'charge_id'), array_column($data['data'],'crt_id'))));
  935. $tag = (new TagService())->getTagMap(array_unique(array_merge_recursive(array_column($data['data'],'priority_id'),array_column($data['data'],'node_id'))));
  936. foreach ($data['data'] as $key => $value){
  937. $data['data'][$key]['crt_time'] = $value['crt_time'] ? date('Y-m-d H:i:s',$value['crt_time']) : '';
  938. $data['data'][$key]['start_time'] = $value['start_time'] ? date('Y-m-d',$value['start_time']) : '';
  939. $data['data'][$key]['end_time'] = $value['end_time'] ? date('Y-m-d',$value['end_time']) : '';
  940. $data['data'][$key]['crt_name'] = $emp[$value['crt_id']] ?? '';
  941. $data['data'][$key]['charge_name'] = $emp[$value['charge_id']] ?? '';
  942. $data['data'][$key]['state_title'] = ItemNode::State_Type[$value['state']] ?? "";
  943. $priority_tmp = $tag[$value['priority_id']] ?? [];
  944. $data['data'][$key]['priority_title'] = $priority_tmp['title'] ?? '';
  945. $data['data'][$key]['priority_code'] = $priority_tmp['code'] ?? '';
  946. $node_tmp = $tag[$value['node_id']] ?? [];
  947. $data['data'][$key]['node_title'] = $node_tmp['title'] ?? '';
  948. $data['data'][$key]['node_code'] = $node_tmp['code'] ?? '';
  949. }
  950. return $data;
  951. }
  952. //项目节点任务
  953. public function itemNodeMissionEdit($data,$user){
  954. list($status,$msg) = $this->itemNodeMissionRule($data, $user, false);
  955. if(!$status) return [$status,$msg];
  956. try {
  957. DB::beginTransaction();
  958. $model = ItemNodeMission::where('id', $data['id'])->first();
  959. $old_employee_id = $model->charge_id;
  960. $tableName = $model->getTable();
  961. $model->title = $data['title'] ?? '';
  962. $model->mark = $data['mark'] ?? "";
  963. $model->start_time = $data['start_time'] ?? 0;
  964. $model->end_time = $data['end_time'] ?? 0;
  965. $model->is_delivery_required = $data['is_delivery_required'] ?? 0;
  966. $model->entrust_type = $data['entrust_type'] ?? 0;
  967. $model->charge_id = $data['charge_id'] ?? 0;
  968. $model->mission_id = $data['mission_id'] ?? 0;
  969. $model->mission_weight = $data['mission_weight'] ?? 0;
  970. $model->is_review_required = $data['is_review_required'] ?? 0;
  971. $model->review_id = $data['review_id'] ?? 0;
  972. $model->priority_id = $data['priority_id'] ?? 0;
  973. $model->save();
  974. $time = time();
  975. ItemNodeMissionDetails::where('del_time',0)
  976. ->where('item_node_mission_id', $model->id)
  977. ->update(['del_time' => $time]);
  978. $this->saveNodeMissionDetail($model->id, $time, $data);
  979. // 人员项目节点任务表
  980. $this->saveNodeMissionEmployee($model->id, $time, $data, $user, $old_employee_id);
  981. list($status, $msg) = CustomFieldSettingService::syncCustomFieldData($model->id, $tableName, $data, $user);
  982. if (! $status) {
  983. DB::rollBack();
  984. return [false, $msg];
  985. }
  986. DB::commit();
  987. }catch (\Exception $exception){
  988. DB::rollBack();
  989. return [false,$exception->getMessage()];
  990. }
  991. return [true, ''];
  992. }
  993. public function itemNodeMissionAdd($data,$user){
  994. list($status,$msg) = $this->itemNodeMissionRule($data, $user);
  995. if(!$status) return [$status,$msg];
  996. try {
  997. DB::beginTransaction();
  998. $model = new ItemNodeMission();
  999. $model->item_id = $data['item_id'] ?? 0;
  1000. $tableName = $model->getTable();
  1001. $model->code = $this->generateBillNo([
  1002. 'top_depart_id' => $user['top_depart_id'],
  1003. 'type' => ItemNodeMission::Order_type,
  1004. 'period' => date("Ym", time())
  1005. ]);
  1006. $model->title = $data['title'] ?? '';
  1007. $model->mark = $data['mark'] ?? "";
  1008. $model->start_time = $data['start_time'] ?? 0;
  1009. $model->end_time = $data['end_time'] ?? 0;
  1010. $model->is_delivery_required = $data['is_delivery_required'] ?? 0;
  1011. $model->entrust_type = $data['entrust_type'] ?? 0;
  1012. $model->charge_id = $data['charge_id'] ?? 0;
  1013. $model->mission_id = $data['mission_id'] ?? 0;
  1014. $model->mission_weight = $data['mission_weight'] ?? 0;
  1015. $model->is_review_required = $data['is_review_required'] ?? 0;
  1016. $model->review_id = $data['review_id'] ?? 0;
  1017. $model->priority_id = $data['priority_id'] ?? 0;
  1018. $model->crt_id = $user['id'];
  1019. $model->top_depart_id = $data['top_depart_id'];
  1020. $model->save();
  1021. $time = time();
  1022. $this->saveNodeMissionDetail($model->id, $time, $data);
  1023. // 人员项目节点任务表
  1024. $this->saveNodeMissionEmployee($model->id, $time, $data, $user);
  1025. list($status, $msg) = CustomFieldSettingService::syncCustomFieldData($model->id, $tableName, $data, $user);
  1026. if (!$status) {
  1027. DB::rollBack();
  1028. return [false, $msg];
  1029. }
  1030. DB::commit();
  1031. }catch (\Exception $exception){
  1032. DB::rollBack();
  1033. return [false,$exception->getMessage()];
  1034. }
  1035. return [true, ''];
  1036. }
  1037. private function saveNodeMissionEmployee($id, $time, $data, $user, $old_employee_id = 0){
  1038. if($old_employee_id != $data['charge_id']){
  1039. ItemNodeMissionEmployee::where('del_time',0)
  1040. ->where('item_node_mission_id', $id)
  1041. ->where('data_id', $old_employee_id)
  1042. ->delete();
  1043. ItemNodeMissionEmployee::insert([
  1044. 'item_node_mission_id' => $id,
  1045. 'item_node_id' => $data['item_node_id'],
  1046. 'item_id' => $data['item_id'],
  1047. 'data_id' => $data['charge_id'],
  1048. 'top_depart_id' => $user['top_depart_id'],
  1049. 'crt_time' => $time
  1050. ]);
  1051. }
  1052. }
  1053. private function saveNodeMissionDetail($id, $time, $data){
  1054. if(! empty($data['man_list'])){
  1055. $unit = [];
  1056. foreach ($data['man_list'] as $value){
  1057. $unit[] = [
  1058. 'item_id' => $data['item_id'],
  1059. 'item_node_id' => $data['item_node_id'],
  1060. 'item_node_mission_id' => $id,
  1061. 'type' => $value['type'],
  1062. 'data_id' => $value['data_id'],
  1063. 'crt_time' => $time,
  1064. 'top_depart_id' => $value['top_depart_id'],
  1065. ];
  1066. }
  1067. if(! empty($unit)) ItemNodeMissionDetails::insert($unit);
  1068. }
  1069. if(! empty($data['device_list'])){
  1070. $receipt = [];
  1071. foreach ($data['device_list'] as $value){
  1072. $receipt[] = [
  1073. 'item_id' => $data['item_id'],
  1074. 'item_node_id' => $data['item_node_id'],
  1075. 'item_node_mission_id' => $id,
  1076. 'type' => $value['type'],
  1077. 'data_id' => $value['data_id'],
  1078. 'crt_time' => $time,
  1079. 'top_depart_id' => $value['top_depart_id'],
  1080. ];
  1081. }
  1082. if(! empty($receipt)) ItemNodeMissionDetails::insert($receipt);
  1083. }
  1084. }
  1085. private function getNodeMissionDetail($id){
  1086. $data = ItemNodeMissionDetails::where('del_time',0)
  1087. ->where('item_node_mission_id', $id)
  1088. ->get()->toArray();
  1089. $id = $id2 = [];
  1090. foreach ($data as $value){
  1091. if($value['type'] == ItemNodeMissionDetails::type_one) {
  1092. $id[] = $value['data_id'];
  1093. }else{
  1094. $id2[] = $value['data_id'];
  1095. }
  1096. }
  1097. $map = Employee::whereIn('id', $id)->select('title','id','number')->get()->toArray();
  1098. $map = array_column($map,null,'id');
  1099. $map2 = Device::whereIn('id', $id2)->select('code','id','title')->get()->toArray();
  1100. $map2 = array_column($map2,null,'id');
  1101. $unit = $receipt = [];
  1102. foreach ($data as $value){
  1103. if($value['type'] == ItemNodeMissionDetails::type_one) {
  1104. $tmp = $map[$value['data_id']] ?? [];
  1105. $unit[] = [
  1106. 'type' => $value['type'],
  1107. 'data_id' => $value['data_id'],
  1108. 'data_title' => $tmp['title'],
  1109. 'data_code' => $tmp['number'],
  1110. ];
  1111. }else{
  1112. $tmp = $map2[$value['data_id']] ?? [];
  1113. $receipt[] = [
  1114. 'type' => $value['type'],
  1115. 'data_id' => $value['data_id'],
  1116. 'data_title' => $tmp['title'] ?? "",
  1117. 'data_code' => $tmp['code'] ?? "",
  1118. ];
  1119. }
  1120. }
  1121. return [
  1122. 'man_list' => $unit,
  1123. 'device_list' => $receipt,
  1124. ];
  1125. }
  1126. public function itemNodeMissionDel($data){
  1127. if($this->isEmpty($data,'id')) return [false,'请选择数据!'];
  1128. try {
  1129. DB::beginTransaction();
  1130. $time = time();
  1131. ItemNodeMission::where('del_time',0)
  1132. ->whereIn('id',$data['id'])
  1133. ->update(['del_time' => $time]);
  1134. ItemNodeMissionDetails::where('del_time',0)
  1135. ->whereIn('item_node_mission_id', $data['id'])
  1136. ->update(['del_time' => $time]);
  1137. DB::commit();
  1138. }catch (\Exception $exception){
  1139. DB::rollBack();
  1140. return [false,$exception->getMessage()];
  1141. }
  1142. return [true, ''];
  1143. }
  1144. public function itemNodeMissionDetail($data, $user){
  1145. if($this->isEmpty($data,'id')) return [false,'请选择数据!'];
  1146. $customer = ItemNodeMission::where('del_time',0)
  1147. ->withCustomData($user)
  1148. ->where('id',$data['id'])
  1149. ->first();
  1150. if(empty($customer)) return [false,'项目节点任务不存在或已被删除'];
  1151. $customer->getFormattedCustomFields();// 自定义数据附件处理
  1152. $customer = $customer->toArray();
  1153. $customer['start_time'] = ! empty($customer['start_time']) ? date("Y-m-d", $customer['start_time']) : "";
  1154. $customer['end_time'] = ! empty($customer['end_time']) ? date("Y-m-d", $customer['end_time']) : "";
  1155. $customer['crt_name'] = Employee::where('id',$customer['crt_id'])->value('title');
  1156. $customer['charge_name'] = Employee::where('id',$customer['charge_id'])->value('title');
  1157. $customer['crt_time'] = $customer['crt_time'] ? date("Y-m-d H:i:s",$customer['crt_time']): '';
  1158. $customer['state_title'] = ItemNodeMission::State_Type[$customer['state']] ?? '';
  1159. $tag = (new TagService())->getTagMap(array_unique([$customer['priority_id'], $customer['mission_id'] ]));
  1160. $priority_tmp = $tag[$customer['priority_id']] ?? [];
  1161. $customer['priority_title'] = $priority_tmp['title'] ?? '';
  1162. $customer['priority_code'] = $priority_tmp['code'] ?? '';
  1163. $node_tmp = $tag[$customer['mission_id']] ?? [];
  1164. $customer['mission_title'] = $node_tmp['title'] ?? '';
  1165. $customer['mission_code'] = $node_tmp['code'] ?? '';
  1166. $details = $this->getNodeMissionDetail($data['id']);
  1167. $customer = array_merge($customer, $details);
  1168. return [true, $customer];
  1169. }
  1170. public function itemNodeMissionCommon($data,$user, $field = []){
  1171. if(empty($field)) $field = ItemNodeMission::$field;
  1172. $model = ItemNodeMission::TopAndEmployeeClear($user,$data);
  1173. $model = $model->where('del_time',0)
  1174. ->select($field)
  1175. ->orderby('id', 'desc');
  1176. if(! empty($data['title'])) $model->where('title', 'LIKE', '%'.$data['title'].'%');
  1177. if(! empty($data['code'])) $model->where('code', 'LIKE', '%'.$data['code'].'%');
  1178. if(! empty($data['id'])) $model->whereIn('id', $data['id']);
  1179. if(isset($data['state'])) $model->where('state', $data['state']);
  1180. if(! empty($data['crt_time'][0]) && ! empty($data['crt_time'][1])) {
  1181. $return = $this->changeDateToTimeStampAboutRange($data['crt_time']);
  1182. $model->where('crt_time','>=',$return[0]);
  1183. $model->where('crt_time','<=',$return[1]);
  1184. }
  1185. return $model;
  1186. }
  1187. public function itemNodeMissionList($data,$user){
  1188. $model = $this->itemNodeMissionCommon($data, $user);
  1189. $list = $this->limit($model,'',$data);
  1190. $list = $this->fillNodeMissionData($list);
  1191. return [true, $list];
  1192. }
  1193. public function itemNodeMissionRule(&$data, $user, $is_add = true){
  1194. $data['top_depart_id'] = $user['top_depart_id'];
  1195. if(empty($data['item_node_id'])) return [false, '项目节点ID不能为空'];
  1196. $item = ItemNode::where('id', $data['item_node_id'])->where('del_time',0)->first();
  1197. if(empty($item)) return [false, '项目节点不存在或已被删除'];
  1198. $item = $item->toArray();
  1199. $data['item_id'] = $item['item_id'];
  1200. if(empty($data['title'])) return [false, '任务名称不能为空'];
  1201. if(! empty($data['start_time'])) $data['start_time'] = $this->changeDateToDate($data['start_time']);
  1202. if(! empty($data['end_time'])) $data['end_time'] = $this->changeDateToDate($data['end_time'],true);
  1203. $itemStartTime = $item['start_time'];
  1204. $itemEndTime = $item['end_time'];
  1205. if (!empty($data['start_time'])) {
  1206. $inputStartTime = $data['start_time'];
  1207. if ($itemStartTime > 0 && $inputStartTime < $itemStartTime) {
  1208. return [false, '任务开始时间不能早于项目节点开始时间:' . date('Y-m-d', $itemStartTime)];
  1209. }
  1210. }
  1211. if (!empty($data['end_time'])) {
  1212. $inputEndTime = $data['end_time'];
  1213. if ($itemEndTime > 0 && $inputEndTime > $itemEndTime) {
  1214. return [false, '任务结束时间不能晚于项目节点结束时间:' . date('Y-m-d', $itemEndTime)];
  1215. }
  1216. }
  1217. if(! empty($data['man_list'])) {
  1218. foreach ($data['man_list'] as $key => $value){
  1219. if(empty($value['type'])) return [false, '类型不能为空'];
  1220. if(empty($value['data_id'])) return [false, '人员不能为空'];
  1221. $data['man_list'][$key]['top_depart_id'] = $data['top_depart_id'];
  1222. }
  1223. list($status, $msg) = $this->checkArrayRepeat($data['man_list'],'data_id','人员');
  1224. if(! $status) return [false, $msg];
  1225. }
  1226. if(! empty($data['device_list'])) {
  1227. foreach ($data['device_list'] as $key => $value){
  1228. if(empty($value['type'])) return [false, '类型不能为空'];
  1229. if(empty($value['data_id'])) return [false, '设备ID不能为空'];
  1230. $data['device_list'][$key]['top_depart_id'] = $data['top_depart_id'];
  1231. }
  1232. list($status, $msg) = $this->checkArrayRepeat($data['device_list'],'data_id','设备');
  1233. if(! $status) return [false, $msg];
  1234. }
  1235. if($is_add){
  1236. $bool = ItemNodeMission::where('item_node_id',$data['item_node_id'])
  1237. ->where('top_depart_id', $data['top_depart_id'])
  1238. ->where('title', $data['title'])
  1239. ->where('del_time',0)
  1240. ->exists();
  1241. }else{
  1242. if(empty($data['id'])) return [false,'ID不能为空'];
  1243. $bool = ItemNodeMission::where('title', $data['title'])
  1244. ->where('item_node_id',$data['item_node_id'])
  1245. ->where('top_depart_id', $data['top_depart_id'])
  1246. ->where('id','<>',$data['id'])
  1247. ->where('del_time',0)
  1248. ->exists();
  1249. }
  1250. if($bool) return [false, '该项目节点下任务名称已存在'];
  1251. return [true, ''];
  1252. }
  1253. public function fillNodeMissionData($data){
  1254. if(empty($data['data'])) return $data;
  1255. $emp = (new EmployeeService())->getEmployeeMap(array_unique(array_merge_recursive(array_column($data['data'],'charge_id'), array_column($data['data'],'crt_id'))));
  1256. $tag = (new TagService())->getTagMap(array_unique(array_merge_recursive(array_column($data['data'],'priority_id'),array_column($data['data'],'mission_id'))));
  1257. foreach ($data['data'] as $key => $value){
  1258. $data['data'][$key]['crt_time'] = $value['crt_time'] ? date('Y-m-d H:i:s',$value['crt_time']) : '';
  1259. $data['data'][$key]['start_time'] = $value['start_time'] ? date('Y-m-d',$value['start_time']) : '';
  1260. $data['data'][$key]['end_time'] = $value['end_time'] ? date('Y-m-d',$value['end_time']) : '';
  1261. $data['data'][$key]['crt_name'] = $emp[$value['crt_id']] ?? '';
  1262. $data['data'][$key]['charge_name'] = $emp[$value['charge_id']] ?? '';
  1263. $data['data'][$key]['state_title'] = ItemNode::State_Type[$value['state']] ?? "";
  1264. $priority_tmp = $tag[$value['priority_id']] ?? [];
  1265. $data['data'][$key]['priority_title'] = $priority_tmp['title'] ?? '';
  1266. $data['data'][$key]['priority_code'] = $priority_tmp['code'] ?? '';
  1267. $node_tmp = $tag[$value['mission_id']] ?? [];
  1268. $data['data'][$key]['mission_title'] = $node_tmp['title'] ?? '';
  1269. $data['data'][$key]['mission_code'] = $node_tmp['code'] ?? '';
  1270. }
  1271. return $data;
  1272. }
  1273. }