WorkFlowService.php 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. <?php
  2. namespace App\Service;
  3. use App\Model\Draft;
  4. use App\Model\Employee;
  5. use App\Model\WorkFlowInstances;
  6. use App\Model\WorkFlowInstancesNodes;
  7. use App\Model\WorkFlowTemplates;
  8. use Illuminate\Support\Facades\DB;
  9. class WorkFlowService extends Service
  10. {
  11. public function workFlowEdit($data,$user){
  12. list($status,$msg) = $this->workFlowRule($data, $user, false);
  13. if(!$status) return [$status,$msg];
  14. try {
  15. DB::beginTransaction();
  16. $model = WorkFlowTemplates::where('id', $data['id'])->first();
  17. $model->code = $data['code'] ?? '';
  18. $model->title = $data['title'] ?? '';
  19. $model->content = $data['content'] ?? '';
  20. $model->save();
  21. DB::commit();
  22. }catch (\Exception $exception){
  23. DB::rollBack();
  24. return [false,$exception->getMessage()];
  25. }
  26. return [true, ''];
  27. }
  28. public function workFlowAdd($data,$user){
  29. list($status,$msg) = $this->workFlowRule($data, $user);
  30. if(!$status) return [$status,$msg];
  31. try {
  32. DB::beginTransaction();
  33. $model = new WorkFlowTemplates();
  34. $model->code = $data['code'] ?? '';
  35. $model->title = $data['title'] ?? '';
  36. $model->content = $data['content'] ?? '';
  37. $model->crt_id = $user['id'];
  38. $model->top_depart_id = $user['top_depart_id'];
  39. $model->save();
  40. DB::commit();
  41. }catch (\Exception $exception){
  42. DB::rollBack();
  43. return [false,$exception->getMessage()];
  44. }
  45. return [true, ''];
  46. }
  47. public function workFlowDetail($data, $user){
  48. if($this->isEmpty($data,'id')) return [false,'请选择数据!'];
  49. $customer = WorkFlowTemplates::where('del_time',0)
  50. ->where('id',$data['id'])
  51. ->first();
  52. if(empty($customer)) return [false,'审批流不存在或已被删除'];
  53. $customer = $customer->toArray();
  54. $customer['crt_name'] = Employee::where('id',$customer['crt_id'])->value('title');
  55. $customer['crt_time'] = $customer['crt_time'] ? date("Y-m-d H:i:s",$customer['crt_time']): '';
  56. return [true, $customer];
  57. }
  58. public function workFlowDel($data, $user){
  59. if($this->isEmpty($data,'id')) return [false,'请选择数据!'];
  60. $customer = WorkFlowTemplates::where('del_time',0)
  61. ->where('id',$data['id'])
  62. ->first();
  63. if(empty($customer)) return [false,'审批流不存在或已被删除'];
  64. $customer->del_time = time();
  65. $customer->save();
  66. return [true, ''];
  67. }
  68. public function workFlowCommon($data,$user, $field = []){
  69. if(empty($field)) $field = WorkFlowTemplates::$field;
  70. $model = WorkFlowTemplates::TopClear($user,$data);
  71. $model = $model->where('del_time',0)
  72. ->select($field)
  73. ->orderby('id', 'desc');
  74. if(! empty($data['title'])) $model->where('title', 'LIKE', '%'.$data['title'].'%');
  75. if(! empty($data['code'])) $model->where('code', 'LIKE', '%'.$data['code'].'%');
  76. if(! empty($data['id'])) $model->whereIn('id', $data['id']);
  77. if(! empty($data['crt_time'][0]) && ! empty($data['crt_time'][1])) {
  78. $return = $this->changeDateToTimeStampAboutRange($data['crt_time']);
  79. $model->where('crt_time','>=',$return[0]);
  80. $model->where('crt_time','<=',$return[1]);
  81. }
  82. return $model;
  83. }
  84. public function workFlowList($data,$user){
  85. $model = $this->workFlowCommon($data, $user);
  86. $list = $this->limit($model,'',$data);
  87. $list = $this->fillData($list);
  88. return [true, $list];
  89. }
  90. public function workFlowRule(&$data, $user, $is_add = true) {
  91. if(empty($data['title'])) return [false, '审批流名称不能为空'];
  92. if(empty($data['code'])) return [false, '审批流编码不能为空'];
  93. if(empty($data['content'])) return [false, '审批流内容不能为空'];
  94. // 1. JSON 格式校验与转换
  95. $content = $data['content'];
  96. if (is_string($content)) {
  97. $content = json_decode($content, true);
  98. if (json_last_error() !== JSON_ERROR_NONE) {
  99. return [false, '审批流内容格式错误,不是有效的JSON'];
  100. }
  101. }
  102. // 2. 结构完整性校验
  103. if (!isset($content['nodes']) || !is_array($content['nodes'])) {
  104. return [false, '审批流配置缺少节点(nodes)信息'];
  105. }
  106. if (!isset($content['edges']) || !is_array($content['edges'])) {
  107. return [false, '审批流配置缺少连线(edges)信息'];
  108. }
  109. $data['content'] = $content;
  110. // 4. 业务唯一性校验
  111. $query = WorkFlowTemplates::where('code', $data['code'])
  112. ->where('top_depart_id', $user['top_depart_id'])
  113. ->where('del_time', 0);
  114. if (!$is_add) {
  115. if (empty($data['id'])) return [false, 'ID不能为空'];
  116. $query->where('id', '<>', $data['id']);
  117. }
  118. if ($query->exists()) return [false, '审批流编码已存在'];
  119. return [true, ''];
  120. }
  121. public function fillData($data){
  122. if(empty($data['data'])) return $data;
  123. $emp = (new EmployeeService())->getEmployeeMap(array_unique(array_merge_recursive(array_column($data['data'],'charge_id'), array_column($data['data'],'crt_id'))));
  124. foreach ($data['data'] as $key => $value){
  125. $data['data'][$key]['crt_time'] = $value['crt_time'] ? date('Y-m-d H:i:s',$value['crt_time']) : '';
  126. $data['data'][$key]['crt_name'] = $emp[$value['crt_id']] ?? '';
  127. }
  128. return $data;
  129. }
  130. /**
  131. * 触发审批流实例
  132. * * @param string $templateCode 审批流唯一编码
  133. * @param int $documentId 业务单据ID
  134. * @param string $documentType 业务模型类名
  135. * @param array $user 当前操作用户信息
  136. */
  137. public function triggerWorkflow($templateID, $documentId, $documentType, $user)
  138. {
  139. // 1. 获取对应的审批流模板
  140. $template = WorkFlowTemplates::where('id', $templateID)
  141. ->where('top_depart_id', $user['top_depart_id'])
  142. ->where('del_time', 0)
  143. ->first();
  144. if (!$template) return [false, '审批模板不存在'];
  145. // 2. 创建流程主实例
  146. $instance = WorkFlowInstances::create([
  147. 'template_id' => $template->id,
  148. 'document_id' => $documentId,
  149. 'document_type' => $documentType,
  150. 'status' => WorkFlowInstances::status_two, // 激活
  151. 'crt_id' => $user['id'],
  152. 'crt_time' => time(),
  153. 'upd_time' => time(),
  154. 'top_depart_id' => $user['top_depart_id']
  155. ]);
  156. // 获取前端原始 JSON 中的节点和连线 [cite: 1]
  157. $nodes = $template->content['nodes'];
  158. $edges = $template->content['edges'];
  159. // 3. 准备批量插入的节点数据
  160. $insertNodes = [];
  161. foreach ($nodes as $node) {
  162. $nodeKey = $node['id'];
  163. // 从 edges 中寻找当前节点的前置 (source 为谁) 和 后置 (target 为谁) [cite: 1]
  164. // 这里的 source 和 target 是 edges 顶层的字符串 ID
  165. $prev = collect($edges)->where('target', $nodeKey)->pluck('source')->first();
  166. $next = collect($edges)->where('source', $nodeKey)->pluck('target')->first();
  167. $tempAssignees = $node['data']['assignees'] ?? [];
  168. foreach($tempAssignees as $k => $person) {
  169. $tempAssignees[$k]['is_pass'] = 0; // 0-未审,1-通过,2-驳回
  170. $tempAssignees[$k]['mark'] = '';
  171. $tempAssignees[$k]['pass_time'] = 0;
  172. }
  173. $insertNodes[] = [
  174. 'instance_id' => $instance->id,
  175. 'node_key' => $nodeKey,
  176. 'label' => $node['label'] ?? '未命名节点',
  177. 'prev_node_key' => $prev, // 上级节点 ID
  178. 'next_node_key' => $next, // 下级节点 ID
  179. // 审批人快照存储 [cite: 1]
  180. 'assignees' => json_encode($tempAssignees),
  181. // 审批类型:1 会签,2 或签 [cite: 1]
  182. 'approval_type' => $node['data']['type'] ?? 2,
  183. // 初始状态逻辑:如果没有前置节点,说明是首节点,直接进入“审批中”状态
  184. 'status' => $prev ? 0 : 1,
  185. 'handled_time' => 0,
  186. 'crt_time' => time(),
  187. 'upd_time' => time(),
  188. 'crt_id' => $user['id'],
  189. 'top_depart_id' => $user['top_depart_id']
  190. ];
  191. }
  192. // 4. 写入节点实例表
  193. WorkFlowInstancesNodes::insert($insertNodes);
  194. return [true, $instance->id];
  195. }
  196. /**
  197. * 获取当前用户的已办(已处理)审核列表
  198. */
  199. public function getMyHandledApprovals($data, $user)
  200. {
  201. $userId = $user['id'];
  202. $topDepartId = $user['top_depart_id'];
  203. // 1. 构造查询对象
  204. $model = WorkFlowInstancesNodes::where('del_time', 0)
  205. ->where('top_depart_id', $topDepartId)
  206. // 核心条件变更:
  207. // 条件A:我是审批人之一
  208. ->whereRaw('JSON_CONTAINS(assignees, JSON_OBJECT("id", ?))', [$userId])
  209. // 条件B:包含我已经审批通过(1)或审批驳回(2)的情况
  210. ->whereRaw('(JSON_CONTAINS(assignees, JSON_OBJECT("id", ?, "is_pass", 1)) OR JSON_CONTAINS(assignees, JSON_OBJECT("id", ?, "is_pass", 2)))', [$userId, $userId])
  211. ->select('*')
  212. ->orderBy('id', 'desc');
  213. $pageData = $this->limit($model, '', $data);
  214. if (empty($pageData['data'])) return [true, $pageData];
  215. // 2. 提取当前页的所有流程实例 ID
  216. $instanceIds = array_unique(array_column($pageData['data'], 'instance_id'));
  217. // 3. 获取流程实例及其关联的模板
  218. $instances = WorkFlowInstances::with(['template'])
  219. ->whereIn('id', $instanceIds)
  220. ->get()
  221. ->keyBy('id');
  222. // --- 处理动态业务单据数据 ---
  223. // 4. 按业务类型分组,批量查出单据的 code 和 title
  224. $documentGroups = [];
  225. foreach ($instances as $ins) {
  226. $documentGroups[$ins->document_type][] = $ins->document_id;
  227. }
  228. $documentDataMap = []; // 存储结构: [type][id] => ['code' => ..., 'title' => ...]
  229. foreach ($documentGroups as $type => $ids) {
  230. $docs = DB::table($type)
  231. ->whereIn('id', array_unique($ids))
  232. ->select('id', 'code', 'title')
  233. ->get()
  234. ->keyBy('id')
  235. ->toArray();
  236. $documentDataMap[$type] = $docs;
  237. }
  238. // 5. 组装最终返回数据
  239. foreach ($pageData['data'] as $key => $node) {
  240. $instance = $instances[$node['instance_id']] ?? null;
  241. // 获取关联业务表的具体数据
  242. $docDetail = null;
  243. if ($instance) {
  244. $docDetail = $documentDataMap[$instance->document_type][$instance->document_id] ?? null;
  245. }
  246. // 解析出我个人的审批意见和审批时间
  247. $assignees = is_string($node['assignees']) ? json_decode($node['assignees'], true) : $node['assignees'];
  248. $mySnapshot = collect($assignees)->firstWhere('id', $userId);
  249. $pageData['data'][$key] = [
  250. 'node_instance_id' => $node['id'],
  251. 'instance_id' => $node['instance_id'],
  252. 'node_label' => $node['label'],
  253. 'document_id' => $instance->document_id ?? 0,
  254. 'document_type' => $instance->document_type ?? '',
  255. 'document_code' => $docDetail->code ?? '', // 业务单据编号
  256. 'document_title' => $docDetail->title ?? '', // 业务单据标题
  257. 'workflow_title' => $instance->template->title ?? '', // 审批模板名
  258. 'crt_time' => !empty($instance->crt_time->timestamp) ? date('Y-m-d H:i:s', $instance->crt_time->timestamp) : '',
  259. 'approval_type' => $node['approval_type'],
  260. 'approval_type_title'=> WorkFlowInstancesNodes::approval_type[$node['approval_type']] ?? '',
  261. // --- 已办列表额外返回:我当时的处理结果 ---
  262. 'my_handle_status' => $mySnapshot['is_pass'] ?? 0, // 我个人的处理状态:1-通过,2-驳回
  263. 'my_handle_status_title' => WorkFlowInstancesNodes::is_pass_title[$mySnapshot['is_pass']] ?? '', // 我个人的处理状态:1-通过,2-驳回
  264. 'my_handle_remark' => $mySnapshot['mark'] ?? '', // 我写下的审批意见
  265. 'my_handle_time_fmt' => !empty($mySnapshot['pass_time']) ? date('Y-m-d H:i:s', $mySnapshot['pass_time']) : '', // 我的审批时间
  266. // 整个流程目前的整体状态(方便前端展示:审批中、已通过、已驳回)
  267. 'instance_status' => $instance->status ?? 0,
  268. ];
  269. }
  270. return [true, $pageData];
  271. }
  272. /**
  273. * 获取当前用户的待办审核列表
  274. */
  275. public function getMyPendingApprovals($data, $user)
  276. {
  277. $userId = $user['id'];
  278. $topDepartId = $user['top_depart_id'];
  279. // 1. 构造查询对象
  280. $model = WorkFlowInstancesNodes::where('del_time', 0)
  281. ->where('top_depart_id', $topDepartId)
  282. ->where('status', 1)
  283. ->whereRaw('JSON_CONTAINS(assignees, JSON_OBJECT("id", ?))', [$userId])
  284. ->whereRaw('NOT JSON_CONTAINS(assignees, JSON_OBJECT("id", ?, "is_pass", 1))', [$userId])
  285. ->select('*')
  286. ->orderBy('id', 'desc');
  287. $pageData = $this->limit($model, '', $data);
  288. if (empty($pageData['data'])) return [true, $pageData];
  289. // 2. 提取当前页的所有流程实例 ID
  290. $instanceIds = array_unique(array_column($pageData['data'], 'instance_id'));
  291. // 3. 获取流程实例及其关联的模板
  292. $instances = WorkFlowInstances::with(['template'])
  293. ->whereIn('id', $instanceIds)
  294. ->get()
  295. ->keyBy('id');
  296. // --- 处理动态业务单据数据 ---
  297. // 4. 按业务类型分组,批量查出单据的 code 和 title
  298. $documentGroups = [];
  299. foreach ($instances as $ins) {
  300. $documentGroups[$ins->document_type][] = $ins->document_id;
  301. }
  302. $documentDataMap = []; // 存储结构: [type][id] => ['code' => ..., 'title' => ...]
  303. foreach ($documentGroups as $type => $ids) {
  304. // 这里根据你的 document_type (如 'item') 动态查询
  305. // 假设你的业务表都有 code 和 title 字段
  306. $docs = DB::table($type)
  307. ->whereIn('id', array_unique($ids))
  308. ->select('id', 'code', 'title')
  309. ->get()
  310. ->keyBy('id')
  311. ->toArray();
  312. $documentDataMap[$type] = $docs;
  313. }
  314. // 5. 组装最终返回数据
  315. foreach ($pageData['data'] as $key => $node) {
  316. $instance = $instances[$node['instance_id']] ?? null;
  317. // 获取关联业务表的具体数据
  318. $docDetail = null;
  319. if ($instance) {
  320. $docDetail = $documentDataMap[$instance->document_type][$instance->document_id] ?? null;
  321. }
  322. $pageData['data'][$key] = [
  323. 'node_instance_id' => $node['id'],
  324. 'instance_id' => $node['instance_id'],
  325. 'node_label' => $node['label'],
  326. 'document_id' => $instance->document_id ?? 0,
  327. 'document_type' => $instance->document_type ?? '',
  328. // --- 新增字段 ---
  329. 'document_code' => $docDetail->code ?? '', // 业务单据编号
  330. 'document_title' => $docDetail->title ?? '', // 业务单据标题
  331. 'workflow_title' => $instance->template->title ?? '', // 审批模板名
  332. 'crt_time' => !empty($instance->crt_time->timestamp) ? date('Y-m-d H:i:s', $instance->crt_time->timestamp) : '',
  333. 'approval_type' => $node['approval_type'],
  334. 'approval_type_title' => WorkFlowInstancesNodes::approval_type[$node['approval_type']] ?? '',
  335. ];
  336. }
  337. return [true, $pageData];
  338. }
  339. public function approval($data, $user)
  340. {
  341. DB::beginTransaction(); // 开启最外层事务
  342. try {
  343. // 1. 执行审批逻辑
  344. list($status, $msg, $result) = $this->approve($data, $user);
  345. if (!$status) {
  346. DB::rollBack();
  347. return [false, $msg];
  348. }
  349. // 2. 如果流程终结(通过或驳回),执行业务结算
  350. if ($result == 1 || $result == 2) {
  351. $instance_id = $msg;
  352. $this->businessSettle($result, $instance_id);
  353. }
  354. DB::commit();
  355. return [true, ''];
  356. } catch (\Exception $e) {
  357. DB::rollBack();
  358. return [false, "审批失败: " . $e->getMessage()];
  359. }
  360. }
  361. /**
  362. * @param int $nodeInstanceId 节点实例ID
  363. * @param int $status 结果:2-通过,3-驳回
  364. * @param string $remark 意见
  365. * @param array $user 当前操作人
  366. *
  367. * 业务结果说明:0-审批中(继续等待), 1-最终通过(业务单据可改为已完成), 2-已驳回(业务单据可改为已拒绝)
  368. */
  369. public function approve($data, $user)
  370. {
  371. $nodeInstanceId = $data['node_instance_id'] ?? 0;
  372. $status = $data['status'] ?? 2;
  373. $remark = $data['mark'] ?? '';
  374. $currentNode = WorkFlowInstancesNodes::where('del_time',0)
  375. ->where('id', $nodeInstanceId)
  376. ->where('top_depart_id', $user['top_depart_id'])
  377. ->first();
  378. if (!$currentNode || $currentNode->status != 1) return [false, '环节无效或已处理', 0];
  379. $assignees = is_string($currentNode->assignees) ? json_decode($currentNode->assignees, true) : $currentNode->assignees;
  380. $myIndex = collect($assignees)->search(fn($item) => $item['id'] == $user['id']);
  381. if ($myIndex === false) return [false, '您不在审批人名单中', 0];
  382. $time = time();
  383. $assignees[$myIndex]['mark'] = $remark;
  384. $assignees[$myIndex]['pass_time'] = $time;
  385. // --- 情况 A:驳回 ---
  386. if ($status == 3) {
  387. $currentNode->status = 3;
  388. $currentNode->handled_time = $time;
  389. $assignees[$myIndex]['is_pass'] = 2;
  390. $currentNode->assignees = $assignees;
  391. $currentNode->save();
  392. WorkFlowInstances::where('id', $currentNode->instance_id)->update(['status' => WorkFlowInstances::status_four]);
  393. DB::commit();
  394. return [true, $currentNode->instance_id, 2];
  395. }
  396. // --- 情况 B:通过 ---
  397. $assignees[$myIndex]['is_pass'] = 1;
  398. $currentNode->assignees = $assignees;
  399. $shouldMoveToNext = false;
  400. if ($currentNode->approval_type == 2) {
  401. $shouldMoveToNext = true;
  402. } else {
  403. $unPassedCount = collect($assignees)->where('is_pass', '!=', 1)->count();
  404. if ($unPassedCount == 0) {
  405. $shouldMoveToNext = true;
  406. }
  407. }
  408. $finalResult = 0; // 默认:还在审批中
  409. if ($shouldMoveToNext) {
  410. $currentNode->status = 2;
  411. $currentNode->handled_time = $time;
  412. $currentNode->save();
  413. if (!empty($currentNode->next_node_key)) {
  414. $hasActiveNext = $this->activateNextNode($currentNode->instance_id, $currentNode->next_node_key);
  415. if (!$hasActiveNext) {
  416. // 如果逻辑上虽然有key但没找到下个节点,也视为终结
  417. WorkFlowInstances::where('id', $currentNode->instance_id)->update(['status' => WorkFlowInstances::status_three]);
  418. $finalResult = 1;
  419. }
  420. } else {
  421. // 没有下个节点,流程最终终结
  422. WorkFlowInstances::where('id', $currentNode->instance_id)->update(['status' => WorkFlowInstances::status_three]);
  423. $finalResult = 1; // 返回 1,表示业务层面可以执行“生效”动作
  424. }
  425. } else {
  426. // 会签中,还有人没审
  427. $currentNode->save();
  428. $finalResult = 0;
  429. }
  430. return [true, $currentNode->instance_id, $finalResult];
  431. }
  432. private function activateNextNode($instanceId, $nextNodeKey)
  433. {
  434. $nextNode = WorkFlowInstancesNodes::where('instance_id', $instanceId)
  435. ->where('node_key', $nextNodeKey)
  436. ->where('del_time',0)
  437. ->first();
  438. if ($nextNode) {
  439. $nextNode->status = 1;
  440. $nextNode->save();
  441. return true;
  442. }
  443. return false;
  444. }
  445. /**
  446. * 业务结算逻辑
  447. */
  448. public function businessSettle($result, $instance_id)
  449. {
  450. $w = WorkFlowInstances::where('id', $instance_id)->first();
  451. if (empty($w)) throw new \Exception("未找到流程实例");
  452. $draft = Draft::where('del_time', 0)
  453. ->where('document_type', $w->document_type)
  454. ->where('document_id', $w->document_id)
  455. ->where('top_depart_id', $w->top_depart_id)
  456. ->latest()
  457. ->first();
  458. // 审核最终通过
  459. if ($result == 1) {
  460. if (!empty($draft)) {
  461. if ($draft->opt_type == 1) {
  462. // 执行覆盖逻辑
  463. $status = false;
  464. $resMsg = '';
  465. // 动态调用
  466. if ($draft->document_type == 'item') {
  467. list($status, $resMsg) = (new ItemService())->itemEditSave($draft->content, $draft->opt_user);
  468. } elseif ($draft->document_type == 'item_node') {
  469. list($status, $resMsg) = (new ItemService())->itemNodeEditSave($draft->content, $draft->opt_user);
  470. } elseif ($draft->document_type == 'item_node_mission') {
  471. list($status, $resMsg) = (new ItemService())->itemNodeMissionEditSave($draft->content, $draft->opt_user);
  472. }
  473. if (!$status) throw new \Exception("业务数据更新失败: " . $resMsg);
  474. }elseif ($draft->opt_type == 2){
  475. DB::table($w->document_type)->where('id', $w->document_id)->update($draft->content);
  476. }
  477. }
  478. }
  479. // 无论通过还是驳回,重置业务表状态
  480. DB::table($w->document_type)->where('id', $w->document_id)->update(['approval_state' => 0]);
  481. // 清理草稿
  482. if (! empty($draft)) {
  483. $draft->del_time = time();
  484. $draft->save();
  485. }
  486. }
  487. }