DocsController.php 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. <?php
  2. namespace App\Http\Controllers\Api;
  3. use App\Http\Controllers\Controller;
  4. use App\Module\Base;
  5. use App\Module\Docs;
  6. use App\Module\Users;
  7. use App\Tasks\PushTask;
  8. use Cache;
  9. use DB;
  10. use Hhxsv5\LaravelS\Swoole\Task\Task;
  11. use Request;
  12. /**
  13. * @apiDefine docs
  14. *
  15. * 知识库
  16. */
  17. class DocsController extends Controller
  18. {
  19. public function __invoke($method, $action = '')
  20. {
  21. $app = $method ? $method : 'main';
  22. if ($action) {
  23. $app .= "__" . $action;
  24. }
  25. return (method_exists($this, $app)) ? $this->$app() : Base::ajaxError("404 not found (" . str_replace("__", "/", $app) . ").");
  26. }
  27. /**
  28. * 知识库列表
  29. *
  30. * @apiParam {Number} [page] 当前页,默认:1
  31. * @apiParam {Number} [pagesize] 每页显示数量,默认:20,最大:100
  32. */
  33. public function book__lists()
  34. {
  35. $user = Users::authE();
  36. if (Base::isError($user)) {
  37. return $user;
  38. } else {
  39. $user = $user['data'];
  40. }
  41. //
  42. $lists = DB::table('docs_book')
  43. ->where('username', $user['username'])
  44. ->orWhere('role_edit', 'reg')
  45. ->orWhere(function ($query) use ($user) {
  46. $query->where('role_edit', 'private')->where('username', $user['username']);
  47. })
  48. ->orWhere(function ($query) use ($user) {
  49. $query->where('role_edit', 'member')->whereIn('id', function ($query2) use ($user) {
  50. $query2->select('bookid')
  51. ->from('docs_users')
  52. ->where('username', $user['username'])
  53. ->whereRaw(env('DB_PREFIX') . 'docs_book.id = bookid');
  54. });
  55. })
  56. ->orderByDesc('id')
  57. ->paginate(Min(Max(Base::nullShow(Request::input('pagesize'), 10), 1), 100));
  58. $lists = Base::getPageList($lists);
  59. if ($lists['total'] == 0) {
  60. return Base::retError('暂无知识库', $lists);
  61. }
  62. return Base::retSuccess('success', $lists);
  63. }
  64. /**
  65. * 添加/修改知识库
  66. *
  67. * @apiParam {Number} id 知识库数据ID
  68. * @apiParam {String} title 知识库名称
  69. */
  70. public function book__add()
  71. {
  72. $user = Users::authE();
  73. if (Base::isError($user)) {
  74. return $user;
  75. } else {
  76. $user = $user['data'];
  77. }
  78. //
  79. $id = intval(Request::input('id'));
  80. $title = trim(Request::input('title'));
  81. if ($id > 0) {
  82. $role = Docs::checkRole($id, 'edit');
  83. if (Base::isError($role)) {
  84. return $role;
  85. }
  86. }
  87. if (mb_strlen($title) < 2 || mb_strlen($title) > 100) {
  88. return Base::retError('标题限制2-100个字!');
  89. }
  90. if ($id > 0) {
  91. // 修改
  92. $row = Base::DBC2A(DB::table('docs_book')->where('id', $id)->first());
  93. if (empty($row)) {
  94. return Base::retError('知识库不存在或已被删除!');
  95. }
  96. $data = [
  97. 'title' => $title,
  98. ];
  99. DB::table('docs_book')->where('id', $id)->update($data);
  100. return Base::retSuccess('修改成功!', $data);
  101. } else {
  102. // 添加
  103. $data = [
  104. 'username' => $user['username'],
  105. 'title' => $title,
  106. 'indate' => Base::time(),
  107. ];
  108. $id = DB::table('docs_book')->insertGetId($data);
  109. if (empty($id)) {
  110. return Base::retError('系统繁忙,请稍后再试!');
  111. }
  112. $data['id'] = $id;
  113. return Base::retSuccess('添加成功!', $data);
  114. }
  115. }
  116. /**
  117. * 设置知识库
  118. *
  119. * @apiParam {Number} id 知识库数据ID
  120. * @apiParam {String} role_edit
  121. * @apiParam {String} role_view
  122. */
  123. public function book__setting()
  124. {
  125. $user = Users::authE();
  126. if (Base::isError($user)) {
  127. return $user;
  128. } else {
  129. $user = $user['data'];
  130. }
  131. //
  132. $id = intval(Request::input('id'));
  133. $role = Docs::checkRole($id, 'edit');
  134. if (Base::isError($role)) {
  135. return $role;
  136. }
  137. $row = Base::DBC2A(DB::table('docs_book')->where('id', $id)->first());
  138. if (empty($row)) {
  139. return Base::retError('知识库不存在或已被删除!');
  140. }
  141. $setting = Base::string2array($row['setting']);
  142. $type = trim(Request::input('type'));
  143. if ($type == 'save') {
  144. foreach (Request::input() AS $key => $value) {
  145. if (in_array($key, ['role_edit', 'role_view'])) {
  146. $setting[$key] = $value;
  147. }
  148. }
  149. DB::table('docs_book')->where('id', $id)->update([
  150. 'role_edit' => $setting['role_edit'],
  151. 'role_view' => $setting['role_view'],
  152. 'setting' => Base::array2string($setting),
  153. ]);
  154. }
  155. return Base::retSuccess($type == 'save' ? '修改成功!' : 'success', $setting ?: json_decode('{}'));
  156. }
  157. /**
  158. * 删除知识库
  159. *
  160. * @apiParam {Number} id 知识库数据ID
  161. */
  162. public function book__delete()
  163. {
  164. $user = Users::authE();
  165. if (Base::isError($user)) {
  166. return $user;
  167. } else {
  168. $user = $user['data'];
  169. }
  170. //
  171. $id = intval(Request::input('id'));
  172. $row = Base::DBC2A(DB::table('docs_book')->where('id', $id)->first());
  173. if (empty($row)) {
  174. return Base::retError('知识库不存在或已被删除!');
  175. }
  176. if ($row['username'] != $user['username']) {
  177. return Base::retError('此操作仅限知识库负责人!');
  178. }
  179. DB::table('docs_book')->where('id', $id)->delete();
  180. DB::table('docs_section')->where('bookid', $id)->delete();
  181. DB::table('docs_content')->where('bookid', $id)->delete();
  182. return Base::retSuccess('删除成功!');
  183. }
  184. /**
  185. * 成员-列表
  186. *
  187. * @apiParam {Number} id 知识库数据ID
  188. * @apiParam {Number} [page] 当前页,默认:1
  189. * @apiParam {Number} [pagesize] 每页显示数量,默认:20,最大:100
  190. */
  191. public function users__lists()
  192. {
  193. $user = Users::authE();
  194. if (Base::isError($user)) {
  195. return $user;
  196. } else {
  197. $user = $user['data'];
  198. }
  199. //
  200. $id = intval(Request::input('id'));
  201. $role = Docs::checkRole($id, 'edit');
  202. if (Base::isError($role)) {
  203. return $role;
  204. }
  205. $row = Base::DBC2A(DB::table('docs_book')->where('id', $id)->first());
  206. if (empty($row)) {
  207. return Base::retError('知识库不存在或已被删除!');
  208. }
  209. //
  210. $lists = DB::table('docs_book')
  211. ->join('docs_users', 'docs_book.id', '=', 'docs_users.bookid')
  212. ->select(['docs_book.title', 'docs_users.*'])
  213. ->where([
  214. ['docs_book.id', $id],
  215. ])
  216. ->orderByDesc('docs_users.id')->paginate(Min(Max(Base::nullShow(Request::input('pagesize'), 10), 1), 100));
  217. $lists = Base::getPageList($lists);
  218. if ($lists['total'] == 0) {
  219. return Base::retError('未找到任何相关的成员');
  220. }
  221. foreach ($lists['lists'] AS $key => $item) {
  222. $userInfo = Users::username2basic($item['username']);
  223. $lists['lists'][$key]['userimg'] = $userInfo['userimg'];
  224. $lists['lists'][$key]['nickname'] = $userInfo['nickname'];
  225. $lists['lists'][$key]['profession'] = $userInfo['profession'];
  226. }
  227. return Base::retSuccess('success', $lists);
  228. }
  229. /**
  230. * 成员-添加、删除
  231. *
  232. * @apiParam {String} act
  233. * - delete: 删除成员
  234. * - else: 添加成员
  235. * @apiParam {Number} id 知识库数据ID
  236. * @apiParam {Array|String} username 用户名(或用户名组)
  237. */
  238. public function users__join()
  239. {
  240. $user = Users::authE();
  241. if (Base::isError($user)) {
  242. return $user;
  243. } else {
  244. $user = $user['data'];
  245. }
  246. //
  247. $id = intval(Request::input('id'));
  248. $role = Docs::checkRole($id, 'edit');
  249. if (Base::isError($role)) {
  250. return $role;
  251. }
  252. $row = Base::DBC2A(DB::table('docs_book')->where('id', $id)->first());
  253. if (empty($row)) {
  254. return Base::retError('知识库不存在或已被删除!');
  255. }
  256. //
  257. $usernames = Request::input('username');
  258. if (empty($usernames)) {
  259. return Base::retError('参数错误!');
  260. }
  261. if (!is_array($usernames)) {
  262. if (Base::strExists($usernames, ',')) {
  263. $usernames = explode(',', $usernames);
  264. } else {
  265. $usernames = [$usernames];
  266. }
  267. }
  268. //
  269. foreach ($usernames AS $username) {
  270. $inRow = Base::DBC2A(DB::table('docs_users')->where(['bookid' => $id, 'username' => $username])->first());
  271. switch (Request::input('act')) {
  272. case 'delete': {
  273. if ($inRow) {
  274. DB::table('docs_users')->where([
  275. 'bookid' => $id,
  276. 'username' => $username
  277. ])->delete();
  278. }
  279. break;
  280. }
  281. default: {
  282. if (!$inRow && $username != $user['username']) {
  283. DB::table('docs_users')->insert([
  284. 'bookid' => $id,
  285. 'username' => $username,
  286. 'indate' => Base::time()
  287. ]);
  288. }
  289. break;
  290. }
  291. }
  292. }
  293. return Base::retSuccess('操作完成!');
  294. }
  295. /**
  296. * 章节列表
  297. *
  298. * @apiParam {String} act 请求方式,用于判断权限
  299. * - edit: 管理页请求
  300. * - view: 阅读页请求
  301. * @apiParam {Number} bookid 知识库数据ID
  302. */
  303. public function section__lists()
  304. {
  305. $bookid = intval(Request::input('bookid'));
  306. $role = Docs::checkRole($bookid, Request::input('act'));
  307. if (Base::isError($role)) {
  308. return $role;
  309. }
  310. $lists = Base::DBC2A(DB::table('docs_section')
  311. ->where('bookid', $bookid)
  312. ->orderByDesc('inorder')
  313. ->orderByDesc('id')
  314. ->take(500)
  315. ->get());
  316. if (empty($lists)) {
  317. return Base::retError('暂无章节');
  318. }
  319. foreach ($lists AS $key => $item) {
  320. $lists[$key]['icon'] = Base::fillUrl('images/files/' . $item['type'] . '.png');
  321. }
  322. $bookDetail = Base::DBC2A(DB::table('docs_book')->select(['title'])->where('id', $bookid)->first());
  323. return Base::retSuccess('success', [
  324. 'book' => $bookDetail ?: json_decode('{}'),
  325. 'tree' => Base::list2Tree($lists, 'id', 'parentid')
  326. ]);
  327. }
  328. /**
  329. * 添加/修改章节
  330. *
  331. * @apiParam {Number} bookid 知识库数据ID
  332. * @apiParam {String} title 章节名称
  333. * @apiParam {String} type 章节类型
  334. */
  335. public function section__add()
  336. {
  337. $user = Users::authE();
  338. if (Base::isError($user)) {
  339. return $user;
  340. } else {
  341. $user = $user['data'];
  342. }
  343. //
  344. $bookid = intval(Request::input('bookid'));
  345. $role = Docs::checkRole($bookid, 'edit');
  346. if (Base::isError($role)) {
  347. return $role;
  348. }
  349. $bookRow = Base::DBC2A(DB::table('docs_book')->where('id', $bookid)->first());
  350. if (empty($bookRow)) {
  351. return Base::retError('知识库不存在或已被删除!');
  352. }
  353. $count = DB::table('docs_section')->where('bookid', $bookid)->count();
  354. if ($count >= 500) {
  355. return Base::retError(['知识库章节已经超过最大限制(%)!', 500]);
  356. }
  357. //
  358. $id = intval(Request::input('id'));
  359. $title = trim(Request::input('title'));
  360. $type = trim(Request::input('type'));
  361. if (mb_strlen($title) < 2 || mb_strlen($title) > 100) {
  362. return Base::retError('标题限制2-100个字!');
  363. }
  364. if ($id > 0) {
  365. // 修改
  366. $row = Base::DBC2A(DB::table('docs_section')->where('id', $id)->first());
  367. if (empty($row)) {
  368. return Base::retError('知识库不存在或已被删除!');
  369. }
  370. $data = [
  371. 'title' => $title,
  372. ];
  373. DB::table('docs_section')->where('id', $id)->update($data);
  374. return Base::retSuccess('修改成功!', $data);
  375. } else {
  376. // 添加
  377. if (!in_array($type, ['document', 'mind', 'sheet', 'flow', 'folder'])) {
  378. return Base::retError('参数错误!');
  379. }
  380. $parentid = 0;
  381. if ($id < 0) {
  382. $count = Base::DBC2A(DB::table('docs_section')->where('id', abs($id))->where('bookid', $bookid)->count());
  383. if ($count > 0) {
  384. $parentid = abs($id);
  385. }
  386. }
  387. $data = [
  388. 'bookid' => $bookid,
  389. 'parentid' => $parentid,
  390. 'username' => $user['username'],
  391. 'title' => $title,
  392. 'type' => $type,
  393. 'inorder' => intval(DB::table('docs_section')->select(['inorder'])->where('bookid', $bookid)->orderByDesc('inorder')->value('inorder')) + 1,
  394. 'indate' => Base::time(),
  395. ];
  396. $id = DB::table('docs_section')->insertGetId($data);
  397. if (empty($id)) {
  398. return Base::retError('系统繁忙,请稍后再试!');
  399. }
  400. $data['id'] = $id;
  401. return Base::retSuccess('添加成功!', $data);
  402. }
  403. }
  404. /**
  405. * 排序章节
  406. *
  407. * @apiParam {Number} bookid 知识库数据ID
  408. * @apiParam {String} oldsort 旧排序数据
  409. * @apiParam {String} newsort 新排序数据
  410. */
  411. public function section__sort()
  412. {
  413. $user = Users::authE();
  414. if (Base::isError($user)) {
  415. return $user;
  416. } else {
  417. $user = $user['data'];
  418. }
  419. //
  420. $bookid = intval(Request::input('bookid'));
  421. $role = Docs::checkRole($bookid, 'edit');
  422. if (Base::isError($role)) {
  423. return $role;
  424. }
  425. $bookRow = Base::DBC2A(DB::table('docs_book')->where('id', $bookid)->first());
  426. if (empty($bookRow)) {
  427. return Base::retError('知识库不存在或已被删除!');
  428. }
  429. //
  430. $newSort = explode(";", Request::input('newsort'));
  431. if (count($newSort) == 0) {
  432. return Base::retError('参数错误!');
  433. }
  434. //
  435. $count = count($newSort);
  436. foreach ($newSort AS $sort => $item) {
  437. list($newId, $newParentid) = explode(':', $item);
  438. DB::table('docs_section')->where([
  439. 'id' => $newId,
  440. 'bookid' => $bookid
  441. ])->update([
  442. 'inorder' => $count - intval($sort),
  443. 'parentid' => $newParentid
  444. ]);
  445. }
  446. return Base::retSuccess('保存成功!');
  447. }
  448. /**
  449. * 删除章节
  450. *
  451. * @apiParam {Number} id 章节数据ID
  452. */
  453. public function section__delete()
  454. {
  455. $user = Users::authE();
  456. if (Base::isError($user)) {
  457. return $user;
  458. } else {
  459. $user = $user['data'];
  460. }
  461. //
  462. $id = intval(Request::input('id'));
  463. $row = Base::DBC2A(DB::table('docs_section')->where('id', $id)->first());
  464. if (empty($row)) {
  465. return Base::retError('文档不存在或已被删除!');
  466. }
  467. $role = Docs::checkRole($row['bookid'], 'edit');
  468. if (Base::isError($role)) {
  469. return $role;
  470. }
  471. DB::table('docs_section')->where('parentid', $id)->update([ 'parentid' => $row['parentid'] ]);
  472. DB::table('docs_section')->where('id', $id)->delete();
  473. DB::table('docs_content')->where('sid', $id)->delete();
  474. return Base::retSuccess('删除成功!');
  475. }
  476. /**
  477. * 获取章节内容
  478. *
  479. * @apiParam {String} act 请求方式,用于判断权限
  480. * - edit: 管理页请求
  481. * - view: 阅读页请求
  482. * @apiParam {Number|String} id 章节数据ID(或:章节数据ID-历史数据ID)
  483. */
  484. public function section__content()
  485. {
  486. $id = Request::input('id');
  487. $hid = 0;
  488. if (Base::strExists($id, '-')) {
  489. list($id, $hid) = explode("-", $id);
  490. }
  491. $id = intval($id);
  492. $hid = intval($hid);
  493. $row = Base::DBC2A(DB::table('docs_section')->where('id', $id)->first());
  494. if (empty($row)) {
  495. return Base::retError('文档不存在或已被删除!');
  496. }
  497. $role = Docs::checkRole($row['bookid'], Request::input('act'));
  498. if (Base::isError($role)) {
  499. return $role;
  500. }
  501. $whereArray = [];
  502. if ($hid > 0) {
  503. $whereArray[] = ['id', '=', $hid];
  504. }
  505. $whereArray[] = ['sid', '=', $id];
  506. $cRow = Base::DBC2A(DB::table('docs_content')->select(['id AS hid', 'content'])->where($whereArray)->orderByDesc('id')->first());
  507. if (empty($cRow)) {
  508. $cRow = [ 'hid' => 0, 'content' => '' ];
  509. }
  510. return Base::retSuccess('success', array_merge($row, $cRow));
  511. }
  512. /**
  513. * 获取章节历史内容
  514. *
  515. * @apiParam {Number} id 章节数据ID
  516. */
  517. public function section__history()
  518. {
  519. $user = Users::authE();
  520. if (Base::isError($user)) {
  521. return $user;
  522. } else {
  523. $user = $user['data'];
  524. }
  525. //
  526. $id = intval(Request::input('id'));
  527. $row = Base::DBC2A(DB::table('docs_section')->where('id', $id)->first());
  528. if (empty($row)) {
  529. return Base::retError('文档不存在或已被删除!');
  530. }
  531. $role = Docs::checkRole($row['bookid'], 'view');
  532. if (Base::isError($role)) {
  533. return $role;
  534. }
  535. //
  536. $lists = Base::DBC2A(DB::table('docs_content')
  537. ->where('sid', $id)
  538. ->orderByDesc('id')
  539. ->take(50)
  540. ->get());
  541. if (count($lists) <= 1) {
  542. return Base::retError('暂无历史数据');
  543. }
  544. return Base::retSuccess('success', $lists);
  545. }
  546. /**
  547. * 保存章节内容
  548. *
  549. * @apiParam {Number} id 章节数据ID
  550. * @apiParam {Object} [D] Request Payload 提交
  551. * - content: 内容
  552. */
  553. public function section__save()
  554. {
  555. $user = Users::authE();
  556. if (Base::isError($user)) {
  557. return $user;
  558. } else {
  559. $user = $user['data'];
  560. }
  561. //
  562. $id = intval(Request::input('id'));
  563. $row = Base::DBC2A(DB::table('docs_section')->where('id', $id)->first());
  564. if (empty($row)) {
  565. return Base::retError('文档不存在或已被删除!');
  566. }
  567. $role = Docs::checkRole($row['bookid'], 'edit');
  568. if (Base::isError($role)) {
  569. return $role;
  570. }
  571. if ($row['lockdate'] + 60 > Base::time() && $row['lockname'] != $user['username']) {
  572. return Base::retError(['已被会员【%】锁定!', Users::nickname($row['lockname'])]);
  573. }
  574. $D = Base::getContentsParse('D');
  575. if ($row['type'] == 'document') {
  576. $data = Base::json2array($D['content']);
  577. $isRep = false;
  578. preg_match_all("/<img\s*src=\"data:image\/(png|jpg|jpeg);base64,(.*?)\"/s", $data['content'], $matchs);
  579. foreach ($matchs[2] as $key => $text) {
  580. $p = "uploads/docs/document/" . $id . "/";
  581. Base::makeDir(public_path($p));
  582. $p.= md5($text) . "." . $matchs[1][$key];
  583. $r = file_put_contents(public_path($p), base64_decode($text));
  584. if ($r) {
  585. $data['content'] = str_replace($matchs[0][$key], '<img src="' . Base::fillUrl($p) . '"', $data['content']);
  586. $isRep = true;
  587. }
  588. }
  589. if ($isRep == true) {
  590. $D['content'] = Base::array2json($data);
  591. }
  592. }
  593. DB::table('docs_content')->insert([
  594. 'bookid' => $row['bookid'],
  595. 'sid' => $id,
  596. 'content' => $D['content'],
  597. 'username' => $user['username'],
  598. 'indate' => Base::time()
  599. ]);
  600. Docs::notice($id, [ 'type' => 'update' ]);
  601. //
  602. return Base::retSuccess('保存成功!');
  603. }
  604. /**
  605. * 保存章节内容
  606. *
  607. * @apiParam {String} act
  608. * - lock: 锁定
  609. * - unlock: 解锁
  610. * @apiParam {Number} id 章节数据ID
  611. */
  612. public function section__lock()
  613. {
  614. $user = Users::authE();
  615. if (Base::isError($user)) {
  616. return $user;
  617. } else {
  618. $user = $user['data'];
  619. }
  620. //
  621. $id = intval(Request::input('id'));
  622. $act = trim(Request::input('act'));
  623. $row = Base::DBC2A(DB::table('docs_section')->where('id', $id)->first());
  624. if (empty($row)) {
  625. return Base::retError('文档不存在或已被删除!');
  626. }
  627. $role = Docs::checkRole($row['bookid'], 'edit');
  628. if (Base::isError($role)) {
  629. return $role;
  630. }
  631. if ($row['lockdate'] + 60 > Base::time() && $row['lockname'] != $user['username']) {
  632. return Base::retError(['已被会员【%】锁定!', Users::nickname($row['lockname'])]);
  633. }
  634. if ($act == 'lock') {
  635. $upArray = [
  636. 'lockname' => $user['username'],
  637. 'lockdate' => Base::time(),
  638. ];
  639. } else {
  640. $upArray = [
  641. 'lockname' => '',
  642. 'lockdate' => 0,
  643. ];
  644. }
  645. DB::table('docs_section')->where('id', $id)->update($upArray);
  646. $upArray['type'] = $act;
  647. Docs::notice($id, $upArray);
  648. //
  649. return Base::retSuccess($act == 'lock' ? '锁定成功' : '已解除锁定', $upArray);
  650. }
  651. }