ProjectController.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679
  1. <?php
  2. namespace App\Http\Controllers\Api;
  3. use App\Http\Controllers\Controller;
  4. use App\Module\Base;
  5. use App\Module\Users;
  6. use DB;
  7. use Request;
  8. use Session;
  9. /**
  10. * @apiDefine project
  11. *
  12. * 项目
  13. */
  14. class ProjectController extends Controller
  15. {
  16. public function __invoke($method, $action = '')
  17. {
  18. $app = $method ? $method : 'main';
  19. if ($action) {
  20. $app .= "__" . $action;
  21. }
  22. return (method_exists($this, $app)) ? $this->$app() : Base::ajaxError("404 not found (" . str_replace("__", "/", $app) . ").");
  23. }
  24. /**
  25. * 项目列表
  26. *
  27. * @apiParam {Number} [page] 当前页,默认:1
  28. * @apiParam {Number} [pagesize] 每页显示数量,默认:20,最大:100
  29. */
  30. public function lists()
  31. {
  32. $user = Users::authE();
  33. if (Base::isError($user)) {
  34. return $user;
  35. } else {
  36. $user = $user['data'];
  37. }
  38. //
  39. $lists = DB::table('project_lists')
  40. ->join('project_users', 'project_lists.id', '=', 'project_users.projectid')
  41. ->select(['project_lists.*', 'project_users.isowner'])
  42. ->where([
  43. ['project_lists.delete', 0],
  44. ['project_users.type', '成员'],
  45. ['project_users.username', $user['username']]
  46. ])
  47. ->orderByDesc('project_lists.id')->paginate(Min(Max(Base::nullShow(Request::input('pagesize'), 10), 1), 100));
  48. $lists = Base::getPageList($lists);
  49. if ($lists['total'] == 0) {
  50. return Base::retError('未找到任何相关的项目');
  51. }
  52. return Base::retSuccess('success', $lists);
  53. }
  54. /**
  55. * 添加项目
  56. *
  57. * @apiParam {String} title 项目名称
  58. * @apiParam {Array} labels 流程,格式[流程1, 流程2]
  59. */
  60. public function add()
  61. {
  62. $user = Users::authE();
  63. if (Base::isError($user)) {
  64. return $user;
  65. } else {
  66. $user = $user['data'];
  67. }
  68. //项目名称
  69. $title = trim(Request::input('title'));
  70. if (mb_strlen($title) < 2) {
  71. return Base::retError('项目名称不可以少于2个字!');
  72. } elseif (mb_strlen($title) > 32) {
  73. return Base::retError('项目名称最多只能设置32个字!');
  74. }
  75. //流程
  76. $labels = Request::input('labels');
  77. if (!is_array($labels)) $labels = [];
  78. $insertLabels = [];
  79. $inorder = 0;
  80. foreach ($labels AS $label) {
  81. $label = trim($label);
  82. if ($label) {
  83. $insertLabels[] = [
  84. 'title' => $label,
  85. 'inorder' => $inorder++,
  86. ];
  87. }
  88. }
  89. if (empty($insertLabels)) {
  90. $insertLabels[] = [
  91. 'title' => '默认',
  92. 'inorder' => 0,
  93. ];
  94. }
  95. //开始创建
  96. $projectid = DB::table('project_lists')->insertGetId([
  97. 'title' => $title,
  98. 'username' => $user['username'],
  99. 'createuser' => $user['username'],
  100. 'indate' => Base::time()
  101. ]);
  102. if ($projectid) {
  103. DB::table('project_label')->insert($insertLabels);
  104. DB::table('project_log')->insert([
  105. 'type' => '日志',
  106. 'projectid' => $projectid,
  107. 'username' => $user['username'],
  108. 'detail' => '创建项目',
  109. 'indate' => Base::time()
  110. ]);
  111. DB::table('project_users')->insert([
  112. 'type' => '成员',
  113. 'projectid' => $projectid,
  114. 'isowner' => 1,
  115. 'username' => $user['username'],
  116. 'indate' => Base::time()
  117. ]);
  118. return Base::retSuccess('添加成功!');
  119. } else {
  120. return Base::retError('添加失败!');
  121. }
  122. }
  123. /**
  124. * 收藏项目
  125. *
  126. * @apiParam {String} act
  127. * - cancel: 取消收藏
  128. * - else: 添加收藏
  129. * @apiParam {Number} projectid 项目ID
  130. *
  131. * @throws \Throwable
  132. */
  133. public function favor()
  134. {
  135. $user = Users::authE();
  136. if (Base::isError($user)) {
  137. return $user;
  138. } else {
  139. $user = $user['data'];
  140. }
  141. //
  142. $projectid = trim(Request::input('projectid'));
  143. $item = Base::DBC2A(DB::table('project_lists')->where('id', $projectid)->first());
  144. if (empty($item)) {
  145. return Base::retError('项目不存在或已被删除!');
  146. }
  147. return DB::transaction(function () use ($item, $user) {
  148. switch (Request::input('act')) {
  149. case 'cancel': {
  150. if (DB::table('project_users')->where([
  151. 'type' => '收藏',
  152. 'projectid' => $item['id'],
  153. 'username' => $user['username'],
  154. ])->delete()) {
  155. DB::table('project_log')->insert([
  156. 'type' => '日志',
  157. 'projectid' => $item['id'],
  158. 'username' => $user['username'],
  159. 'detail' => '取消收藏',
  160. 'indate' => Base::time()
  161. ]);
  162. return Base::retSuccess('取消成功');
  163. }
  164. return Base::retSuccess('已取消');
  165. }
  166. default: {
  167. $row = Base::DBC2A(DB::table('project_users')->where([
  168. 'type' => '收藏',
  169. 'projectid' => $item['id'],
  170. 'username' => $user['username'],
  171. ])->lockForUpdate()->first());
  172. if (empty($row)) {
  173. DB::table('project_users')->insert([
  174. 'type' => '收藏',
  175. 'projectid' => $item['id'],
  176. 'isowner' => $item['username'] == $user['username'] ? 1 : 0,
  177. 'username' => $user['username'],
  178. 'indate' => Base::time()
  179. ]);
  180. DB::table('project_log')->insert([
  181. 'type' => '日志',
  182. 'projectid' => $item['id'],
  183. 'username' => $user['username'],
  184. 'detail' => '收藏项目',
  185. 'indate' => Base::time()
  186. ]);
  187. return Base::retSuccess('收藏成功');
  188. }
  189. return Base::retSuccess('已收藏');
  190. }
  191. }
  192. });
  193. }
  194. /**
  195. * 重命名项目
  196. *
  197. * @apiParam {Number} projectid 项目ID
  198. * @apiParam {String} title 项目新名称
  199. */
  200. public function rename()
  201. {
  202. $user = Users::authE();
  203. if (Base::isError($user)) {
  204. return $user;
  205. } else {
  206. $user = $user['data'];
  207. }
  208. //
  209. $projectid = trim(Request::input('projectid'));
  210. $item = Base::DBC2A(DB::table('project_lists')->where('id', $projectid)->first());
  211. if (empty($item)) {
  212. return Base::retError('项目不存在或已被删除!');
  213. }
  214. if ($item['username'] != $user['username']) {
  215. return Base::retError('你不是项目负责人!');
  216. }
  217. //
  218. $title = trim(Request::input('title'));
  219. if (mb_strlen($title) < 2) {
  220. return Base::retError('项目名称不可以少于2个字!');
  221. } elseif (mb_strlen($title) > 32) {
  222. return Base::retError('项目名称最多只能设置32个字!');
  223. }
  224. //
  225. DB::table('project_lists')->where('id', $item['id'])->update([
  226. 'title' => $title
  227. ]);
  228. DB::table('project_log')->insert([
  229. 'type' => '日志',
  230. 'projectid' => $item['id'],
  231. 'username' => $user['username'],
  232. 'detail' => '【' . $item['title'] . '】重命名【' . $title . '】',
  233. 'indate' => Base::time()
  234. ]);
  235. //
  236. return Base::retSuccess('修改成功');
  237. }
  238. /**
  239. * 移交项目
  240. *
  241. * @apiParam {Number} projectid 项目ID
  242. * @apiParam {String} username 项目新负责人用户名
  243. *
  244. * @throws \Throwable
  245. */
  246. public function transfer()
  247. {
  248. $user = Users::authE();
  249. if (Base::isError($user)) {
  250. return $user;
  251. } else {
  252. $user = $user['data'];
  253. }
  254. //
  255. $projectid = trim(Request::input('projectid'));
  256. $item = Base::DBC2A(DB::table('project_lists')->where('id', $projectid)->first());
  257. if (empty($item)) {
  258. return Base::retError('项目不存在或已被删除!');
  259. }
  260. if ($item['username'] != $user['username']) {
  261. return Base::retError('你不是项目负责人!');
  262. }
  263. //
  264. $username = trim(Request::input('username'));
  265. if ($username == $item['username']) {
  266. return Base::retError('你已是项目负责人!');
  267. }
  268. $count = DB::table('users')->where('username', $username)->count();
  269. if ($count <= 0) {
  270. return Base::retError('成员用户名(' . $username . ')不存在!');
  271. }
  272. //判断是否已在项目
  273. $count = DB::table('project_users')->where([
  274. 'type' => '成员',
  275. 'projectid' => $item['id'],
  276. 'username' => $username,
  277. ])->count();
  278. if ($count <= 0) {
  279. DB::table('project_users')->insert([
  280. 'type' => '成员',
  281. 'projectid' => $item['id'],
  282. 'isowner' => 0,
  283. 'username' => $username,
  284. 'indate' => Base::time()
  285. ]);
  286. DB::table('project_log')->insert([
  287. 'type' => '日志',
  288. 'projectid' => $item['id'],
  289. 'username' => $username,
  290. 'detail' => '移交项目,自动加入项目',
  291. 'indate' => Base::time()
  292. ]);
  293. }
  294. //开始移交
  295. return DB::transaction(function () use ($user, $username, $item) {
  296. DB::table('project_lists')->where('id', $item['id'])->update([
  297. 'username' => $username
  298. ]);
  299. DB::table('project_log')->insert([
  300. 'type' => '日志',
  301. 'projectid' => $item['id'],
  302. 'username' => $user['username'],
  303. 'detail' => '【' . $item['username'] . '】移交给【' . $username . '】',
  304. 'indate' => Base::time()
  305. ]);
  306. DB::table('project_users')->where([
  307. 'projectid' => $item['id'],
  308. 'username' => $item['username'],
  309. ])->update([
  310. 'isowner' => 0
  311. ]);
  312. DB::table('project_users')->where([
  313. 'projectid' => $item['id'],
  314. 'username' => $username,
  315. ])->update([
  316. 'isowner' => 1
  317. ]);
  318. return Base::retSuccess('移交成功');
  319. });
  320. }
  321. /**
  322. * 删除项目
  323. *
  324. * @apiParam {Number} projectid 项目ID
  325. */
  326. public function delete()
  327. {
  328. $user = Users::authE();
  329. if (Base::isError($user)) {
  330. return $user;
  331. } else {
  332. $user = $user['data'];
  333. }
  334. //
  335. $projectid = trim(Request::input('projectid'));
  336. $item = Base::DBC2A(DB::table('project_lists')->where('id', $projectid)->first());
  337. if (empty($item)) {
  338. return Base::retError('项目不存在或已被删除!');
  339. }
  340. if ($item['username'] != $user['username']) {
  341. return Base::retError('你不是项目负责人!');
  342. }
  343. //
  344. DB::table('project_lists')->where('id', $item['id'])->update([
  345. 'delete' => 1,
  346. 'deletedate' => Base::time()
  347. ]);
  348. DB::table('project_log')->insert([
  349. 'type' => '日志',
  350. 'projectid' => $item['id'],
  351. 'username' => $user['username'],
  352. 'detail' => '删除项目',
  353. 'indate' => Base::time()
  354. ]);
  355. //
  356. return Base::retSuccess('删除成功');
  357. }
  358. /**
  359. * 退出项目
  360. *
  361. * @apiParam {Number} projectid 项目ID
  362. */
  363. public function out()
  364. {
  365. $user = Users::authE();
  366. if (Base::isError($user)) {
  367. return $user;
  368. } else {
  369. $user = $user['data'];
  370. }
  371. //
  372. $projectid = trim(Request::input('projectid'));
  373. $item = Base::DBC2A(DB::table('project_lists')->where('id', $projectid)->first());
  374. if (empty($item)) {
  375. return Base::retError('项目不存在或已被删除!');
  376. }
  377. if ($item['username'] == $user['username']) {
  378. return Base::retError('你是项目负责人,不可退出项目!');
  379. }
  380. $count = DB::table('project_users')->where([
  381. 'type' => '成员',
  382. 'projectid' => $projectid,
  383. 'username' => $user['username'],
  384. ])->count();
  385. if ($count <= 0) {
  386. return Base::retError('你不在项目成员内!');
  387. }
  388. //
  389. DB::table('project_users')->where([
  390. 'type' => '成员',
  391. 'projectid' => $item['id'],
  392. 'username' => $user['username'],
  393. ])->delete();
  394. DB::table('project_log')->insert([
  395. 'type' => '日志',
  396. 'projectid' => $item['id'],
  397. 'username' => $user['username'],
  398. 'detail' => '退出项目',
  399. 'indate' => Base::time()
  400. ]);
  401. //
  402. return Base::retSuccess('退出项目成功');
  403. }
  404. /**
  405. * 项目成员-列表
  406. *
  407. * @apiParam {Number} projectid 项目ID
  408. * @apiParam {Number} [page] 当前页,默认:1
  409. * @apiParam {Number} [pagesize] 每页显示数量,默认:20,最大:100
  410. */
  411. public function users__lists()
  412. {
  413. $user = Users::authE();
  414. if (Base::isError($user)) {
  415. return $user;
  416. } else {
  417. $user = $user['data'];
  418. }
  419. //
  420. $projectid = intval(Request::input('projectid'));
  421. $count = DB::table('project_users')->where([
  422. 'type' => '成员',
  423. 'projectid' => $projectid,
  424. 'username' => $user['username'],
  425. ])->count();
  426. if ($count <= 0) {
  427. return Base::retError('你不在项目成员内!');
  428. }
  429. //
  430. $lists = DB::table('project_lists')
  431. ->join('project_users', 'project_lists.id', '=', 'project_users.projectid')
  432. ->select(['project_lists.title', 'project_users.*'])
  433. ->where([
  434. ['project_lists.id', $projectid],
  435. ['project_lists.delete', 0],
  436. ['project_users.type', '成员'],
  437. ])
  438. ->orderByDesc('project_lists.id')->paginate(Min(Max(Base::nullShow(Request::input('pagesize'), 10), 1), 100));
  439. $lists = Base::getPageList($lists);
  440. if ($lists['total'] == 0) {
  441. return Base::retError('未找到任何相关的成员');
  442. }
  443. foreach ($lists['lists'] AS $key => $item) {
  444. $userInfo = Users::username2basic($item['username']);
  445. $lists['lists'][$key]['userimg'] = $userInfo['userimg'];
  446. $lists['lists'][$key]['nickname'] = $userInfo['nickname'];
  447. $lists['lists'][$key]['profession'] = $userInfo['profession'];
  448. }
  449. return Base::retSuccess('success', $lists);
  450. }
  451. /**
  452. * 项目成员-添加、删除
  453. *
  454. * @apiParam {String} act
  455. * - delete: 删除成员
  456. * - else: 添加成员
  457. * @apiParam {Number} projectid 项目ID
  458. * @apiParam {Array|String} username 用户名(或用户名组)
  459. */
  460. public function users__join()
  461. {
  462. $user = Users::authE();
  463. if (Base::isError($user)) {
  464. return $user;
  465. } else {
  466. $user = $user['data'];
  467. }
  468. //
  469. $projectid = trim(Request::input('projectid'));
  470. $item = Base::DBC2A(DB::table('project_lists')->where('id', $projectid)->first());
  471. if (empty($item)) {
  472. return Base::retError('项目不存在或已被删除!');
  473. }
  474. if ($item['username'] != $user['username']) {
  475. return Base::retError('你是不是项目负责人!');
  476. }
  477. $usernames = Request::input('username');
  478. if (empty($usernames)) {
  479. return Base::retError('参数错误!');
  480. }
  481. if (!is_array($usernames)) {
  482. if (Base::strExists($usernames, ',')) {
  483. $usernames = explode(',', $usernames);
  484. } else {
  485. $usernames = [$usernames];
  486. }
  487. }
  488. //
  489. $logArray = [];
  490. foreach ($usernames AS $username) {
  491. $count = DB::table('project_users')->where([
  492. 'type' => '成员',
  493. 'projectid' => $projectid,
  494. 'username' => $username,
  495. ])->count();
  496. switch (Request::input('act')) {
  497. case 'delete': {
  498. if ($count > 0 && $item['username'] != $username) {
  499. DB::table('project_users')->where([
  500. 'type' => '成员',
  501. 'projectid' => $projectid,
  502. 'username' => $username,
  503. ])->delete();
  504. $logArray[] = [
  505. 'type' => '日志',
  506. 'projectid' => $item['id'],
  507. 'username' => $user['username'],
  508. 'detail' => '将成员【' . $username . '】移出项目',
  509. 'indate' => Base::time()
  510. ];
  511. }
  512. break;
  513. }
  514. default: {
  515. if ($count == 0) {
  516. DB::table('project_users')->insert([
  517. 'type' => '成员',
  518. 'projectid' => $projectid,
  519. 'isowner' => 0,
  520. 'username' => $username,
  521. 'indate' => Base::time()
  522. ]);
  523. $logArray[] = [
  524. 'type' => '日志',
  525. 'projectid' => $item['id'],
  526. 'username' => $username,
  527. 'detail' => '将成员【' . $username . '】加入项目',
  528. 'indate' => Base::time()
  529. ];
  530. }
  531. break;
  532. }
  533. }
  534. }
  535. return Base::retSuccess('操作完成');
  536. }
  537. /**
  538. * 项目任务-列表
  539. *
  540. * @apiParam {Number} projectid 项目ID
  541. * @apiParam {Number} [archived] 是否归档
  542. * - 0: 未归档
  543. * - 1: 已归档
  544. * @apiParam {Number} [page] 当前页,默认:1
  545. * @apiParam {Number} [pagesize] 每页显示数量,默认:20,最大:100
  546. */
  547. public function task__lists()
  548. {
  549. $user = Users::authE();
  550. if (Base::isError($user)) {
  551. return $user;
  552. } else {
  553. $user = $user['data'];
  554. }
  555. //
  556. $projectid = intval(Request::input('projectid'));
  557. $count = DB::table('project_users')->where([
  558. 'type' => '成员',
  559. 'projectid' => $projectid,
  560. 'username' => $user['username'],
  561. ])->count();
  562. if ($count <= 0) {
  563. return Base::retError('你不在项目成员内!');
  564. }
  565. //
  566. $whereArray = [];
  567. $whereArray[] = ['project_lists.id', '=', $projectid];
  568. $whereArray[] = ['project_lists.delete', '=', 0];
  569. if (in_array(intval(Request::input('archived')), [0, 1])) {
  570. $whereArray[] = ['project_task.archived', '=', Request::input('archived')];
  571. }
  572. //
  573. $orderBy = 'project_task.id';
  574. if (intval(Request::input('archived')) === 1) {
  575. $orderBy = 'project_task.archiveddate';
  576. }
  577. //
  578. $lists = DB::table('project_lists')
  579. ->join('project_task', 'project_lists.id', '=', 'project_task.projectid')
  580. ->select(['project_task.*'])
  581. ->where($whereArray)
  582. ->orderByDesc($orderBy)->paginate(Min(Max(Base::nullShow(Request::input('pagesize'), 10), 1), 100));
  583. $lists = Base::getPageList($lists);
  584. if ($lists['total'] == 0) {
  585. return Base::retError('未找到任何相关的任务');
  586. }
  587. return Base::retSuccess('success', $lists);
  588. }
  589. /**
  590. * 项目任务-归档、取消归档
  591. *
  592. * @apiParam {String} act
  593. * - cancel: 取消归档
  594. * - else: 加入归档
  595. * @apiParam {Number} taskid 任务ID
  596. */
  597. public function task__archived()
  598. {
  599. $user = Users::authE();
  600. if (Base::isError($user)) {
  601. return $user;
  602. } else {
  603. $user = $user['data'];
  604. }
  605. //
  606. $taskid = intval(Request::input('taskid'));
  607. $task = Base::DBC2A(DB::table('project_lists')
  608. ->join('project_task', 'project_lists.id', '=', 'project_task.projectid')
  609. ->select(['project_task.projectid', 'project_task.title', 'project_task.archived'])
  610. ->where([
  611. ['project_lists.delete', '=', 0],
  612. ['project_task.id', '=', $taskid],
  613. ])
  614. ->first());
  615. if (empty($task)) {
  616. return Base::retError('任务不存在!');
  617. }
  618. $count = DB::table('project_users')->where([
  619. 'type' => '成员',
  620. 'projectid' => $task['projectid'],
  621. 'username' => $user['username'],
  622. ])->count();
  623. if ($count <= 0) {
  624. return Base::retError('你不在项目成员内!');
  625. }
  626. //
  627. switch (Request::input('act')) {
  628. case 'cancel': {
  629. if ($task['archived'] == 0) {
  630. return Base::retError('任务未归档!');
  631. }
  632. DB::table('project_task')->where('id', $taskid)->update([
  633. 'archived' => 1,
  634. 'archiveddate' => Base::time()
  635. ]);
  636. DB::table('project_log')->insert([
  637. 'type' => '日志',
  638. 'projectid' => $task['projectid'],
  639. 'taskid' => $taskid,
  640. 'username' => $user['username'],
  641. 'detail' => '取消归档【' . $task['title'] . '】',
  642. 'indate' => Base::time()
  643. ]);
  644. return Base::retSuccess('取消归档成功');
  645. }
  646. default: {
  647. if ($task['archived'] == 1) {
  648. return Base::retError('任务已归档!');
  649. }
  650. DB::table('project_task')->where('id', $taskid)->update([
  651. 'archived' => 0,
  652. ]);
  653. DB::table('project_log')->insert([
  654. 'type' => '日志',
  655. 'projectid' => $task['projectid'],
  656. 'taskid' => $taskid,
  657. 'username' => $user['username'],
  658. 'detail' => '归档【' . $task['title'] . '】',
  659. 'indate' => Base::time()
  660. ]);
  661. return Base::retSuccess('加入归档成功');
  662. }
  663. }
  664. }
  665. }