From 09f48c32c7ee10ad94d7ea64fc7e3098b6138203 Mon Sep 17 00:00:00 2001 From: weifs <605403358@qq.com> Date: Wed, 19 Apr 2023 17:19:28 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9A=E5=B7=A5=E4=BD=9C=E6=B5=81?= =?UTF-8?q?=E5=89=8D=E7=AB=AF=E8=BF=9B=E5=BA=A6=20-=2095%?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/Api/WorkflowController.php | 58 ++++++++- resources/assets/js/pages/manage.vue | 13 +- .../pages/manage/components/DialogWrapper.vue | 4 +- .../assets/js/pages/manage/review/details.vue | 30 +++-- .../assets/js/pages/manage/review/index.vue | 111 +++++++++++++----- resources/assets/js/store/actions.js | 27 +++++ resources/assets/js/store/state.js | 3 + .../sass/pages/components/dialog-wrapper.scss | 19 +++ resources/assets/sass/pages/page-review.scss | 8 ++ resources/views/push/bot.blade.php | 18 +-- 10 files changed, 238 insertions(+), 53 deletions(-) diff --git a/app/Http/Controllers/Api/WorkflowController.php b/app/Http/Controllers/Api/WorkflowController.php index d5482d179..ed690a38b 100755 --- a/app/Http/Controllers/Api/WorkflowController.php +++ b/app/Http/Controllers/Api/WorkflowController.php @@ -2,16 +2,16 @@ namespace App\Http\Controllers\Api; -use Cache; use Request; -use Carbon\Carbon; use App\Models\User; use App\Module\Base; use App\Module\Ihttp; +use App\Tasks\PushTask; use App\Models\WebSocketDialog; use App\Models\WorkflowProcMsg; use App\Exceptions\ApiException; use App\Models\WebSocketDialogMsg; +use Hhxsv5\LaravelS\Swoole\Task\Task; /** * @apiDefine workflow @@ -47,6 +47,28 @@ class WorkflowController extends AbstractController } } + /** + * @api {get} api/workflow/user/department 02. 获取当前用户部门 + * + * @apiDescription 需要token身份 + * @apiVersion 1.0.0 + * @apiGroup workflow + * @apiName user__department + * + * @apiQuery {Number} id 流程ID + * + * @apiSuccess {Number} ret 返回状态码(1正确、0错误) + * @apiSuccess {String} msg 返回信息(错误描述) + * @apiSuccess {Object} data 返回数据 + */ + public function user__department() + { + // User::auth(); + // $data['id'] = intval(Request::input('id')); + // $workflow = $this->getProcessById($data['id']); + // return Base::retSuccess('success', $workflow); + } + /** * @api {post} api/workflow/procdef/all 02. 查询流程定义 * @@ -211,7 +233,22 @@ class WorkflowController extends AbstractController if($process['is_finished'] == true) { $dialog = WebSocketDialog::checkUserDialog($botUser, $process['start_user_id']); $this->workflowMsg('workflow_submitter', $dialog, $botUser, ['userid' => $data['userid']], $process, $pass); + }else if ($process['candidate']) { + // 下个审批人 + $userid = explode(',', $process['candidate']); + $toUser = User::whereIn('userid', $userid)->get()->toArray(); + foreach ($toUser as $val) { + if ($val['bot']) { + continue; + } + $dialog = WebSocketDialog::checkUserDialog($botUser, $val['userid']); + if (empty($dialog)) { + continue; + } + $this->workflowMsg('workflow_reviewer', $dialog, $botUser, $val, $process,'start'); + } } + // 抄送人 $notifier = $this->handleProcessNode($process, $task['step']); if ($notifier && $pass == 'pass') { @@ -686,6 +723,20 @@ class WorkflowController extends AbstractController $proc_msg->userid = $toUser['userid']; $proc_msg->save(); } + + // 更新工作报告 未读数量 + if($type == 'workflow_reviewer' && $toUser['userid']){ + $params = [ + 'userid' => [ $toUser['userid'], User::auth()->userid() ], + 'msg' => [ + 'type' => 'workflow', + 'action' => 'backlog', + 'userid' => $toUser['userid'], + ] + ]; + Task::deliver(new PushTask($params, false)); + } + return true; } @@ -710,6 +761,9 @@ class WorkflowController extends AbstractController } $val['node_user_list'][$k]['userimg'] = User::getAvatar($info->userid, $info->userimg, $info->email, $info->nickname); } + }else if($val['aprover_id']){ + $info = User::whereUserid($val['aprover_id'])->first(); + $val['userimg'] = $info ? User::getAvatar($info->userid, $info->userimg, $info->email, $info->nickname) : ''; } } $info = User::whereUserid($res['start_user_id'])->first(); diff --git a/resources/assets/js/pages/manage.vue b/resources/assets/js/pages/manage.vue index c3e362ebb..ea50e3603 100644 --- a/resources/assets/js/pages/manage.vue +++ b/resources/assets/js/pages/manage.vue @@ -11,7 +11,7 @@ {{userInfo.nickname}} - +
@@ -90,6 +90,10 @@ v-else-if="item.path === 'workReport' && reportUnreadNumber > 0" class="manage-menu-report-badge" :count="reportUnreadNumber"/> +
@@ -396,6 +400,7 @@ export default { this.$store.dispatch("getUserInfo").catch(_ => {}) this.$store.dispatch("getTaskPriority").catch(_ => {}) this.$store.dispatch("getReportUnread", 0) + this.$store.dispatch("getBacklogUnread", 0) // this.$store.dispatch("needHome").then(_ => { this.needStartHome = true @@ -441,6 +446,7 @@ export default { 'dialogIns', 'reportUnreadNumber', + 'backlogUnreadNumber', ]), ...mapGetters(['dashboardTask']), @@ -686,6 +692,11 @@ export default { this.$store.dispatch("getReportUnread", 1000) } break; + case 'workflow': + if (action == 'backlog') { + this.$store.dispatch("getBacklogUnread", 1000) + } + break; } }, deep: true, diff --git a/resources/assets/js/pages/manage/components/DialogWrapper.vue b/resources/assets/js/pages/manage/components/DialogWrapper.vue index 9853494da..479bfb475 100644 --- a/resources/assets/js/pages/manage/components/DialogWrapper.vue +++ b/resources/assets/js/pages/manage/components/DialogWrapper.vue @@ -2374,7 +2374,7 @@ export default { let domAudits = $(target).parents(".open-review-details") if( domAudits.length > 0 ){ let dataId = domAudits[0].getAttribute("data-id") - if( window.innerWidth < 425 ){ + if( window.innerWidth < 426 ){ this.goForward({name: 'manage-review-details', query: { id: domAudits[0].getAttribute("data-id") } }); }else{ this.approveDetailsShow = true; @@ -2811,4 +2811,4 @@ export default { } } } - + \ No newline at end of file diff --git a/resources/assets/js/pages/manage/review/details.vue b/resources/assets/js/pages/manage/review/details.vue index a1888ec68..1837825e0 100644 --- a/resources/assets/js/pages/manage/review/details.vue +++ b/resources/assets/js/pages/manage/review/details.vue @@ -45,7 +45,7 @@

{{$L('已提交')}}

-

{{ getTimeAgo(item.claim_time) }}

+

{{ getTimeAgo(item.claim_time) }}

{{item.claim_time?.substr(0,16)}}

@@ -56,7 +56,7 @@ >

{{$L('审批')}}

- +

{{item.approver}}

待审批

@@ -68,7 +68,7 @@

-

+

{{ item.identitylink?.state==0 ? ($L('已等待') + " " + getTimeAgo( datas.node_infos[key-1].claim_time,2)) : (item.claim_time ? getTimeAgo(item.claim_time) : '') @@ -77,6 +77,7 @@

{{item.claim_time?.substr(0,16)}}

+

“{{ datas.latest_comment }}”

@@ -111,7 +112,7 @@
- + @@ -131,9 +132,8 @@ export default { data() { return { modalTransferIndex:window.modalTransferIndex, - datas:{ - - } + datas:{}, + showTimeNum:24 } }, watch: { @@ -144,7 +144,6 @@ export default { }, data: { handler(newValue,oldValue) { - console.log(newValue) if(newValue.id){ this.getInfo() } @@ -152,6 +151,17 @@ export default { deep: true }, }, + computed: { + isShowWarningBtn(){ + let is = this.userId == this.datas.start_user_id; + (this.datas.node_infos || []).map(h=>{ + if(h.type != 'starter' && h.is_finished == true) { + is = false; + } + }) + return is; + }, + }, mounted() { this.init() }, @@ -230,7 +240,7 @@ export default { type:"textarea", okText: type == 1 ? "同意" : "拒绝", onOk: (desc) => { - if (!desc) { + if (type !=1 && !desc) { return `请输入审批意见` } this.$store.dispatch("call", { @@ -269,7 +279,7 @@ export default { this.$emit('revocation') }).catch(({msg}) => { $A.modalError(msg); - reject(msg); + resolve(); }); return false }) diff --git a/resources/assets/js/pages/manage/review/index.vue b/resources/assets/js/pages/manage/review/index.vue index 0ede944f5..5963e3f17 100644 --- a/resources/assets/js/pages/manage/review/index.vue +++ b/resources/assets/js/pages/manage/review/index.vue @@ -7,10 +7,10 @@

{{$L('审批中心')}}

- + - +
- +
@@ -51,7 +51,7 @@
- +
@@ -75,7 +75,7 @@
- +
@@ -100,7 +100,7 @@
- +
@@ -116,8 +116,13 @@
+ + + - @@ -146,6 +151,7 @@ + @@ -153,6 +159,7 @@ import list from "./list.vue"; import listDetails from "./details.vue"; import DrawerOverlay from "../../../components/DrawerOverlay"; +import { mapState } from 'vuex' export default { components:{list,listDetails,DrawerOverlay}, name: "review", @@ -195,45 +202,78 @@ export default { addTitle:'', addShow:false, addData: { + department_id:0, type: '', startTime:"", endTime:"", }, addRule: { + department_id:{ type: 'number',required: true, message: this.$L('请选择部门!'), trigger: 'change' }, type: { type: 'string',required: true, message: this.$L('请选择假期类型!'), trigger: 'change' }, startTime: { type: 'string',required: true, message: this.$L('请选择开始时间!'), trigger: 'change' }, endTime:{ type: 'string',required: true, message: this.$L('请选择结束时间!'), trigger: 'change' }, description:{ type: 'string',required: true, message: this.$L('请选择结束时间!'), trigger: 'change' }, }, - selectTypes:["年假","事假","病假","调休","产假","陪产假","婚假","丧假","哺乳假"] + selectTypes:["年假","事假","病假","调休","产假","陪产假","婚假","丧假","哺乳假"], } }, + computed: { + ...mapState([ 'wsMsg','userInfo','userIsAdmin' ]), + departmentList(){ + let departmentNames = (this.userInfo.department_name || '').split(','); + return (this.userInfo.department || []).map((h,index)=>{ + return { + id:h, + name:departmentNames[index] + }; + }) + } + }, + watch: { + wsMsg: { + handler(info) { + const {type, action} = info; + switch (type) { + case 'workflow': + if (action == 'backlog') { + this.tabsClick() + } + break; + } + }, + deep: true, + }, + }, mounted() { - this.tabsValue = "initiated" + this.tabsValue = "backlog" this.tabsClick() this.getProcdef() this.getBacklogList() + this.addData.department_id = this.userInfo.department[0] || 0; }, methods:{ // tab切换事件 tabsClick(val){ - this.tabsValue = val || this.tabsValue - if(val!=""){ - this.approvalType = this.searchState = "all" - } - if(this.tabsValue == 'backlog'){ - this.getBacklogList(); - } - if(this.tabsValue == 'done'){ - this.getDoneList(); - } - if(this.tabsValue == 'notify'){ - this.getNotifyList(); - } - if(this.tabsValue == 'initiated'){ - this.getInitiatedList(); - } + this.__tabsClick && clearTimeout(this.__tabsClick) + this.__tabsClick = setTimeout(() => { + this.tabsValue = val || this.tabsValue + if(val!=""){ + this.approvalType = this.searchState = "all" + } + if(this.tabsValue == 'backlog'){ + this.getBacklogList(); + } + if(this.tabsValue == 'done'){ + this.getDoneList(); + } + if(this.tabsValue == 'notify'){ + this.getNotifyList(); + } + if(this.tabsValue == 'initiated'){ + this.getInitiatedList(); + } + }, 200) }, // 列表点击事件 @@ -244,7 +284,7 @@ export default { this.initiatedList.map(h=>{ h._active = false; }) item._active = true; // - if( window.innerWidth < 425 ){ + if( window.innerWidth < 426 ){ this.goForward({name: 'manage-review-details', query: { id: item.id } }); return; } @@ -398,7 +438,7 @@ export default { url: 'workflow/process/start', data: { proc_name:this.addTitle, - department_id:1, + department_id:this.addData.department_id, var: JSON.stringify(this.addData) }, method: 'post', @@ -421,8 +461,21 @@ export default { } - diff --git a/resources/assets/js/store/actions.js b/resources/assets/js/store/actions.js index 9a3be1d60..0b58fade1 100644 --- a/resources/assets/js/store/actions.js +++ b/resources/assets/js/store/actions.js @@ -457,6 +457,7 @@ export default { dispatch("getProjects").catch(() => {}); dispatch("getDialogs").catch(() => {}); dispatch("getReportUnread", 1000); + dispatch("getBacklogUnread", 1000); dispatch("getTaskForDashboard"); dispatch("dialogMsgRead"); // @@ -485,6 +486,32 @@ export default { }, typeof timeout === "number" ? timeout : 1000) }, + + /** + * 获取审批待办未读数量 + * @param state + * @param dispatch + * @param timeout + */ + getBacklogUnread({state, dispatch}, timeout) { + window.__getBacklogUnread && clearTimeout(window.__getBacklogUnread) + window.__getBacklogUnread = setTimeout(() => { + if (state.userId === 0) { + state.backlogUnreadNumber = 0; + } else { + dispatch("call", { + url: 'workflow/process/findTask', + data: { + page:1, + page_size: 500, + } + }).then(({data}) => { + state.backlogUnreadNumber = data.total || 0; + }).catch(_ => {}); + } + }, typeof timeout === "number" ? timeout : 1000) + }, + /** * 获取/更新会员信息 * @param dispatch diff --git a/resources/assets/js/store/state.js b/resources/assets/js/store/state.js index 9c7a005dc..b00f5efba 100644 --- a/resources/assets/js/store/state.js +++ b/resources/assets/js/store/state.js @@ -179,4 +179,7 @@ export default { apiKeyData: {}, localKeyPair: {}, localKeyLock: false, + + // 审批待办未读数量 + backlogUnreadNumber: 0, }; diff --git a/resources/assets/sass/pages/components/dialog-wrapper.scss b/resources/assets/sass/pages/components/dialog-wrapper.scss index 1ef7e64fa..e5a7e66cf 100644 --- a/resources/assets/sass/pages/components/dialog-wrapper.scss +++ b/resources/assets/sass/pages/components/dialog-wrapper.scss @@ -699,6 +699,25 @@ background-color: $primary-color; } } + + .open-review-details{ + .cause{ + border-bottom: 1px solid #e3e3e3; + border-top: 1px solid #e3e3e3; + padding-bottom: 10px; + margin-top: 10px; + >span:first-child{ + display: inline-block; + padding: 15px 0; + } + } + .btn-raw{ + display: flex; + text-align: center; + gap: 10px; + padding: 10px 0 5px 0; + } + } } } diff --git a/resources/assets/sass/pages/page-review.scss b/resources/assets/sass/pages/page-review.scss index 8d146ca01..06f6e16aa 100644 --- a/resources/assets/sass/pages/page-review.scss +++ b/resources/assets/sass/pages/page-review.scss @@ -220,4 +220,12 @@ align-items: center; gap: 10px; } + + .comment{ + border-radius:5px; + background-color: #eaeaea; + padding: 3px 10px; + margin-top: 5px; + margin-left: 45px; + } } \ No newline at end of file diff --git a/resources/views/push/bot.blade.php b/resources/views/push/bot.blade.php index 65a05fc93..fcf01b202 100755 --- a/resources/views/push/bot.blade.php +++ b/resources/views/push/bot.blade.php @@ -109,15 +109,15 @@ @elseif ($type === 'notice') {{$notice}} @elseif ($type === 'workflow_reviewer') - {{$data->nickname}}提交的「{{$data->proc_def_name}}」待你审批 -
申请人:{{'@'}}{{$data->nickname}} {{$data->department}} + {{$data->nickname}}提交的「{{$data->proc_def_name}}」待你审批 +
申请人:{{'@'}}{{$data->nickname}} {{$data->department}} 审批事由 @if ($data->type) 假期类型:{{$data->type}} @endif 开始时间:{{$data->start_time}} 结束时间:{{$data->end_time}} -
+
@if ($action === 'pass') @elseif ($action === 'refuse') @@ -130,27 +130,27 @@ @endif
@elseif ($type === 'workflow_notifier') - 抄送{{$data->nickname}}提交的「{{$data->proc_def_name}}」记录 -
申请人:{{'@'}}{{$data->nickname}} {{$data->department}} + 抄送{{$data->nickname}}提交的「{{$data->proc_def_name}}」记录 +
申请人:{{'@'}}{{$data->nickname}} {{$data->department}} 审批事由 @if ($data->type) 假期类型:{{$data->type}} @endif 开始时间:{{$data->start_time}} 结束时间:{{$data->end_time}} -
+
@elseif ($type === 'workflow_submitter') - @if ($action === 'pass')您发起的「{{$data->proc_def_name}}」已通过 @else您发起的「{{$data->proc_def_name}}」被{{$data->nickname}}拒绝 @endif -
申请人:{{'@'}}{{$data->nickname}} {{$data->department}} + @if ($action === 'pass')您发起的「{{$data->proc_def_name}}」已通过 @else您发起的「{{$data->proc_def_name}}」被{{$data->nickname}}拒绝 @endif +
申请人:{{'@'}}{{$data->nickname}} {{$data->department}} 审批事由 @if ($data->type) 假期类型:{{$data->type}} @endif 开始时间:{{$data->start_time}} 结束时间:{{$data->end_time}} -
+
@else