mirror of
https://github.com/kuaifan/dootask.git
synced 2026-02-08 23:45:35 +00:00
feat:工作流 - 前端进度 70%
This commit is contained in:
parent
c13aa8d7a4
commit
836d4f8209
@ -63,7 +63,7 @@ class WorkflowController extends AbstractController
|
|||||||
*/
|
*/
|
||||||
public function procdef__all()
|
public function procdef__all()
|
||||||
{
|
{
|
||||||
User::auth('admin');
|
User::auth();
|
||||||
$data['name'] = Request::input('name');
|
$data['name'] = Request::input('name');
|
||||||
$ret = Ihttp::ihttp_post($this->flow_url.'/api/v1/workflow/procdef/findAll', json_encode($data));
|
$ret = Ihttp::ihttp_post($this->flow_url.'/api/v1/workflow/procdef/findAll', json_encode($data));
|
||||||
$procdef = json_decode($ret['ret'] == 1 ? $ret['data'] : '{}', true);
|
$procdef = json_decode($ret['ret'] == 1 ? $ret['data'] : '{}', true);
|
||||||
|
|||||||
@ -2,35 +2,35 @@
|
|||||||
<div class="review-details">
|
<div class="review-details">
|
||||||
<div class="review-details-box">
|
<div class="review-details-box">
|
||||||
<h2 class="review-details-title">
|
<h2 class="review-details-title">
|
||||||
<span>{{data.proc_def_name}}</span>
|
<span>{{datas.proc_def_name}}</span>
|
||||||
<Tag v-if="datas.state == 0" color="cyan">{{$L('待审批')}}</Tag>
|
<Tag v-if="datas.state == 0" color="cyan">{{$L('待审批')}}</Tag>
|
||||||
<Tag v-if="datas.state == 1" color="cyan">{{$L('审批中')}}</Tag>
|
<Tag v-if="datas.state == 1" color="cyan">{{$L('审批中')}}</Tag>
|
||||||
<Tag v-if="datas.state == 2" color="green">{{$L('已通过')}}</Tag>
|
<Tag v-if="datas.state == 2" color="green">{{$L('已通过')}}</Tag>
|
||||||
<Tag v-if="datas.state == 3" color="red">{{$L('已拒绝')}}</Tag>
|
<Tag v-if="datas.state == 3" color="red">{{$L('已拒绝')}}</Tag>
|
||||||
<Tag v-if="datas.state == 4" color="red">{{$L('已撤回')}}</Tag>
|
<Tag v-if="datas.state == 4" color="red">{{$L('已撤回')}}</Tag>
|
||||||
</h2>
|
</h2>
|
||||||
<h3 class="review-details-subtitle"><Avatar :src="data.userimg" size="24"/><span>请假名字</span></h3>
|
<h3 class="review-details-subtitle"><Avatar :src="datas.userimg" size="24"/><span>{{datas.start_user_name}}</span></h3>
|
||||||
<h3 class="review-details-subtitle"><span>{{$L('提交于')}} {{data.start_time}}</span></h3>
|
<h3 class="review-details-subtitle"><span>{{$L('提交于')}} {{datas.start_time}}</span></h3>
|
||||||
<Divider/>
|
<Divider/>
|
||||||
<div class="review-details-text">
|
<div class="review-details-text" v-if="(datas.proc_def_name || '').indexOf('班') == -1">
|
||||||
<h4>{{$L('假期类型')}}</h4>
|
<h4>{{$L('假期类型')}}</h4>
|
||||||
<p>{{data.var?.type}}</p>
|
<p>{{datas.var?.type}}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="review-details-text">
|
<div class="review-details-text">
|
||||||
<h4>{{$L('开始时间')}}</h4>
|
<h4>{{$L('开始时间')}}</h4>
|
||||||
<p>{{data.var?.start_time}}</p>
|
<p>{{datas.var?.start_time}}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="review-details-text">
|
<div class="review-details-text">
|
||||||
<h4>{{$L('结束时间')}}</h4>
|
<h4>{{$L('结束时间')}}</h4>
|
||||||
<p>{{data.var?.end_time}}</p>
|
<p>{{datas.var?.end_time}}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="review-details-text">
|
<div class="review-details-text">
|
||||||
<h4>{{ $L('时长') }}(小时)</h4>
|
<h4>{{ $L('时长') }}({{getTimeDifference(datas.var?.start_time,datas.var?.end_time)['unit']}})</h4>
|
||||||
<p>{{ $L('1天') }}</p>
|
<p>{{ getTimeDifference(datas.var?.start_time,datas.var?.end_time)['time'] }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="review-details-text">
|
<div class="review-details-text">
|
||||||
<h4>{{$L('请假事由')}}</h4>
|
<h4>{{$L('请假事由')}}</h4>
|
||||||
<p>{{data.var?.description}}</p>
|
<p>{{datas.var?.description}}</p>
|
||||||
</div>
|
</div>
|
||||||
<Divider/>
|
<Divider/>
|
||||||
<h3 class="review-details-subtitle">{{$L('审批记录')}}</h3>
|
<h3 class="review-details-subtitle">{{$L('审批记录')}}</h3>
|
||||||
@ -39,7 +39,7 @@
|
|||||||
<TimelineItem v-for="(item,key) in datas.node_infos" :key="key" v-if="item.type == 'starter'" color="green">
|
<TimelineItem v-for="(item,key) in datas.node_infos" :key="key" v-if="item.type == 'starter'" color="green">
|
||||||
<p class="timeline-title">{{$L('提交')}}</p>
|
<p class="timeline-title">{{$L('提交')}}</p>
|
||||||
<div style="display: flex;">
|
<div style="display: flex;">
|
||||||
<Avatar :src="data.userimg" size="38"/>
|
<Avatar :src="data.userimg || datas.userimg" size="38"/>
|
||||||
<div style="margin-left: 10px;flex: 1;">
|
<div style="margin-left: 10px;flex: 1;">
|
||||||
<p class="review-process-name">{{item.approver}}</p>
|
<p class="review-process-name">{{item.approver}}</p>
|
||||||
<p class="review-process-state">{{$L('已提交')}}</p>
|
<p class="review-process-state">{{$L('已提交')}}</p>
|
||||||
@ -56,7 +56,7 @@
|
|||||||
>
|
>
|
||||||
<p class="timeline-title">{{$L('审批')}}</p>
|
<p class="timeline-title">{{$L('审批')}}</p>
|
||||||
<div style="display: flex;">
|
<div style="display: flex;">
|
||||||
<Avatar :src="item.node_user_list[0]?.userimg" size="38"/>
|
<Avatar :src="item.node_user_list && item.node_user_list[0]?.userimg" size="38"/>
|
||||||
<div style="margin-left: 10px;flex: 1;">
|
<div style="margin-left: 10px;flex: 1;">
|
||||||
<p class="review-process-name">{{item.approver}}</p>
|
<p class="review-process-name">{{item.approver}}</p>
|
||||||
<p class="review-process-state" style="color: #6d6d6d;" v-if="!item.identitylink">待审批</p>
|
<p class="review-process-state" style="color: #6d6d6d;" v-if="!item.identitylink">待审批</p>
|
||||||
@ -108,6 +108,7 @@
|
|||||||
</Timeline>
|
</Timeline>
|
||||||
</div>
|
</div>
|
||||||
<div class="review-operation" v-if="datas.state<=1">
|
<div class="review-operation" v-if="datas.state<=1">
|
||||||
|
<div style="flex: 1;"></div>
|
||||||
<Button type="success" v-if="(datas.candidate || '').split(',').indexOf(userId + '') != -1" @click="approve(1)">{{$L('同意')}}</Button>
|
<Button type="success" v-if="(datas.candidate || '').split(',').indexOf(userId + '') != -1" @click="approve(1)">{{$L('同意')}}</Button>
|
||||||
<Button type="error" v-if="(datas.candidate || '').split(',').indexOf(userId + '') != -1" @click="approve(2)">{{$L('拒绝')}}</Button>
|
<Button type="error" v-if="(datas.candidate || '').split(',').indexOf(userId + '') != -1" @click="approve(2)">{{$L('拒绝')}}</Button>
|
||||||
<Button type="warning" v-if="userId == datas.start_user_id" @click="revocation">{{$L('撤销')}}</Button>
|
<Button type="warning" v-if="userId == datas.start_user_id" @click="revocation">{{$L('撤销')}}</Button>
|
||||||
@ -144,6 +145,12 @@ export default {
|
|||||||
deep: true
|
deep: true
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
if(this.$route.query.id){
|
||||||
|
this.data.id = this.$route.query.id;
|
||||||
|
this.getInfo()
|
||||||
|
}
|
||||||
|
},
|
||||||
methods:{
|
methods:{
|
||||||
// 把时间转成几小时前
|
// 把时间转成几小时前
|
||||||
getTimeAgo(time,type) {
|
getTimeAgo(time,type) {
|
||||||
@ -154,13 +161,34 @@ export default {
|
|||||||
} else if (timeDiff < 3600) {
|
} else if (timeDiff < 3600) {
|
||||||
const minutes = Math.floor(timeDiff / 60);
|
const minutes = Math.floor(timeDiff / 60);
|
||||||
return type == 2 ? `${minutes}${this.$L('分钟')}` : `${minutes} ${this.$L('分钟前')}`;
|
return type == 2 ? `${minutes}${this.$L('分钟')}` : `${minutes} ${this.$L('分钟前')}`;
|
||||||
} else {
|
} else if(timeDiff < 3600 * 24) {
|
||||||
const hours = Math.floor(timeDiff / 3600);
|
const hours = Math.floor(timeDiff / 3600);
|
||||||
return type == 2 ? `${hours}${this.$L('小时')}` : `${hours} ${this.$L('小时前')}`;
|
return type == 2 ? `${hours}${this.$L('小时')}` : `${hours} ${this.$L('小时前')}`;
|
||||||
|
} else {
|
||||||
|
const days = Math.floor(timeDiff / 3600 / 24);
|
||||||
|
return type == 2 ? `${days}${this.$L('天')}` : `${days} ${this.$L('天')}`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 获取时间差
|
||||||
|
getTimeDifference(startTime,endTime) {
|
||||||
|
const currentTime = new Date(endTime);
|
||||||
|
const timeDiff = (currentTime - new Date(startTime)) / 1000; // convert to seconds
|
||||||
|
if (timeDiff < 60) {
|
||||||
|
return {time:timeDiff,unit:this.$L('秒')};
|
||||||
|
} else if (timeDiff < 3600) {
|
||||||
|
const minutes = Math.floor(timeDiff / 60);
|
||||||
|
return {time:minutes,unit:this.$L('分钟')};
|
||||||
|
} else if(timeDiff < 3600 * 24) {
|
||||||
|
const hours = Math.floor(timeDiff / 3600);
|
||||||
|
return {time:hours,unit:this.$L('小时')};
|
||||||
|
} else {
|
||||||
|
const days = Math.floor(timeDiff / 3600 / 24);
|
||||||
|
return {time:days,unit:this.$L('天')};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 获取详情
|
// 获取详情
|
||||||
getInfo(){
|
getInfo(){
|
||||||
|
this.datas = this.data
|
||||||
this.$store.dispatch("call", {
|
this.$store.dispatch("call", {
|
||||||
method: 'get',
|
method: 'get',
|
||||||
url: 'workflow/process/detail',
|
url: 'workflow/process/detail',
|
||||||
@ -197,7 +225,7 @@ export default {
|
|||||||
this.$store.dispatch("call", {
|
this.$store.dispatch("call", {
|
||||||
url: 'workflow/task/complete',
|
url: 'workflow/task/complete',
|
||||||
data: {
|
data: {
|
||||||
task_id: this.data.task_id,
|
task_id: this.datas.task_id,
|
||||||
pass: type == 1,
|
pass: type == 1,
|
||||||
comment: desc,
|
comment: desc,
|
||||||
}
|
}
|
||||||
@ -221,8 +249,8 @@ export default {
|
|||||||
this.$store.dispatch("call", {
|
this.$store.dispatch("call", {
|
||||||
url: 'workflow/task/withdraw',
|
url: 'workflow/task/withdraw',
|
||||||
data: {
|
data: {
|
||||||
task_id: this.data.task_id,
|
task_id: this.datas.task_id,
|
||||||
proc_inst_id: this.data.id,
|
proc_inst_id: this.datas.id,
|
||||||
}
|
}
|
||||||
}).then(({msg}) => {
|
}).then(({msg}) => {
|
||||||
resolve();
|
resolve();
|
||||||
|
|||||||
@ -7,15 +7,14 @@
|
|||||||
<div class="review-nav">
|
<div class="review-nav">
|
||||||
<h1>{{$L('审批中心')}}</h1>
|
<h1>{{$L('审批中心')}}</h1>
|
||||||
</div>
|
</div>
|
||||||
<Button :loading="loadIng > 0" type="primary" @click="" style="margin-right:10px;">{{$L('发起请假')}}</Button>
|
<Button v-for="item in procdefList" :loading="loadIng > 0" type="primary" @click="initiate(item)" style="margin-right:10px;">{{item.name}}</Button>
|
||||||
<Button :loading="loadIng > 0" type="primary" @click="">{{$L('加班申请')}}</Button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Tabs :value="tabsValue" @on-click="tabsClick" style="margin: 0 20px;height: 100%;">
|
<Tabs :value="tabsValue" @on-click="tabsClick" style="margin: 0 20px;height: 100%;">
|
||||||
<TabPane :label="$L('待办') + (backlogList.length > 0 ? ('('+backlogList.length+')') : '')" name="backlog" style="height: 100%;">
|
<TabPane :label="$L('待办') + (backlogTotal > 0 ? ('('+backlogTotal+')') : '')" name="backlog" style="height: 100%;">
|
||||||
<div class="review-main-search">
|
<div class="review-main-search">
|
||||||
<div style="display: flex;gap: 10px;">
|
<div style="display: flex;gap: 10px;">
|
||||||
<Select v-model="approvalType" style="width: 150px;">
|
<Select v-model="approvalType" @on-change="tabsClick('')" style="width: 150px;">
|
||||||
<Option v-for="item in approvalList" :value="item.value" :key="item.value">{{ item.label }}</Option>
|
<Option v-for="item in approvalList" :value="item.value" :key="item.value">{{ item.label }}</Option>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
@ -26,18 +25,18 @@
|
|||||||
<div class="review-main-list">
|
<div class="review-main-list">
|
||||||
<div @click.stop="clickList(item,key)" v-for="(item,key) in backlogList">
|
<div @click.stop="clickList(item,key)" v-for="(item,key) in backlogList">
|
||||||
<list :class="{ 'review-list-active': item._active }" :data="item"></list>
|
<list :class="{ 'review-list-active': item._active }" :data="item"></list>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="review-main-right">
|
<div class="review-main-right">
|
||||||
<listDetails :data="details" @approve="tabsClick" @revocation="tabsClick"></listDetails>
|
<listDetails v-if="!detailsShow" :data="details" @approve="tabsClick" @revocation="tabsClick"></listDetails>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</TabPane>
|
</TabPane>
|
||||||
<TabPane label="已办" name="done">
|
<TabPane label="已办" name="done">
|
||||||
<div class="review-main-search">
|
<div class="review-main-search">
|
||||||
<div style="display: flex;gap: 10px;">
|
<div style="display: flex;gap: 10px;">
|
||||||
<Select v-model="approvalType" style="width: 150px;">
|
<Select v-model="approvalType" @on-change="tabsClick('')" style="width: 150px;">
|
||||||
<Option v-for="item in approvalList" :value="item.value" :key="item.value">{{ item.label }}</Option>
|
<Option v-for="item in approvalList" :value="item.value" :key="item.value">{{ item.label }}</Option>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
@ -46,13 +45,13 @@
|
|||||||
<div v-else class="review-mains">
|
<div v-else class="review-mains">
|
||||||
<div class="review-main-left">
|
<div class="review-main-left">
|
||||||
<div class="review-main-list">
|
<div class="review-main-list">
|
||||||
<div @click.stop="clickList(item,key)" v-for="(item,key) in doneList">
|
<div @click.stop="clickList(item,key)" v-for="(item,key) in doneList" >
|
||||||
<list :class="{ 'review-list-active': item._active }" :data="item"></list>
|
<list :class="{ 'review-list-active': item._active }" :data="item"></list>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="review-main-right">
|
<div class="review-main-right">
|
||||||
<listDetails :data="details" @approve="tabsClick" @revocation="tabsClick"></listDetails>
|
<listDetails v-if="!detailsShow" :data="details" @approve="tabsClick" @revocation="tabsClick"></listDetails>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</TabPane>
|
</TabPane>
|
||||||
@ -60,7 +59,7 @@
|
|||||||
<div class="review-main-search">
|
<div class="review-main-search">
|
||||||
<div class="review-main-search">
|
<div class="review-main-search">
|
||||||
<div style="display: flex;gap: 10px;">
|
<div style="display: flex;gap: 10px;">
|
||||||
<Select v-model="approvalType" style="width: 150px;">
|
<Select v-model="approvalType" @on-change="tabsClick('')" style="width: 150px;">
|
||||||
<Option v-for="item in approvalList" :value="item.value" :key="item.value">{{ item.label }}</Option>
|
<Option v-for="item in approvalList" :value="item.value" :key="item.value">{{ item.label }}</Option>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
@ -76,17 +75,17 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="review-main-right">
|
<div class="review-main-right">
|
||||||
<listDetails :data="details" @approve="tabsClick" @revocation="tabsClick"></listDetails>
|
<listDetails v-if="!detailsShow" :data="details" @approve="tabsClick" @revocation="tabsClick"></listDetails>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</TabPane>
|
</TabPane>
|
||||||
<TabPane :label="$L('已发起')" name="initiated">
|
<TabPane :label="$L('已发起')" name="initiated">
|
||||||
<div class="review-main-search">
|
<div class="review-main-search">
|
||||||
<div style="display: flex;gap: 10px;">
|
<div style="display: flex;gap: 10px;">
|
||||||
<Select v-model="approvalType" style="width: 150px;">
|
<Select v-model="approvalType" @on-change="tabsClick('')" style="width: 150px;">
|
||||||
<Option v-for="item in approvalList" :value="item.value" :key="item.value">{{ item.label }}</Option>
|
<Option v-for="item in approvalList" :value="item.value" :key="item.value">{{ item.label }}</Option>
|
||||||
</Select>
|
</Select>
|
||||||
<Select v-model="searchState" style="width: 150px;">
|
<Select v-model="searchState" @on-change="tabsClick('')" style="width: 150px;">
|
||||||
<Option v-for="item in searchStateList" :value="item.value" :key="item.value">{{ item.label }}</Option>
|
<Option v-for="item in searchStateList" :value="item.value" :key="item.value">{{ item.label }}</Option>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
@ -101,33 +100,71 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="review-main-right">
|
<div class="review-main-right">
|
||||||
<listDetails :data="details" @approve="tabsClick" @revocation="tabsClick"></listDetails>
|
<listDetails v-if="!detailsShow" :data="details" @approve="tabsClick" @revocation="tabsClick"></listDetails>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</TabPane>
|
</TabPane>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!--详情-->
|
||||||
|
<DrawerOverlay v-model="detailsShow" placement="right" :size="600">
|
||||||
|
<listDetails v-if="detailsShow" :data="details" @approve="tabsClick" @revocation="tabsClick" style="height: 100%;border-radius: 10px;"></listDetails>
|
||||||
|
</DrawerOverlay>
|
||||||
|
|
||||||
|
<!--发起-->
|
||||||
|
<Modal v-model="addShow" :title="$L(addTitle)" :mask-closable="false">
|
||||||
|
<Form ref="initiateRef" :model="addData" :rules="addRule" label-width="auto" @submit.native.prevent>
|
||||||
|
<FormItem v-if="(addTitle || '').indexOf('班') == -1" prop="type" :label="$L('假期类型')">
|
||||||
|
<Select v-model="addData.type" :placeholder="$L('请选择')">
|
||||||
|
<Option v-for="(item, index) in selectTypes" :value="item" :key="index">{{ item }}</Option>
|
||||||
|
</Select>
|
||||||
|
</FormItem>
|
||||||
|
<FormItem prop="startTime" :label="$L('开始时间')">
|
||||||
|
<DatePicker type="datetime" format="yyyy-MM-dd HH:mm"
|
||||||
|
v-model="addData.startTime"
|
||||||
|
:value="addData.startTime"
|
||||||
|
@on-change="(e)=>{ addData.startTime = e }"
|
||||||
|
:placeholder="$L('请选择开始时间')" style="width: 100%"
|
||||||
|
></DatePicker>
|
||||||
|
</FormItem>
|
||||||
|
<FormItem prop="endTime" :label="$L('结束时间')">
|
||||||
|
<DatePicker type="datetime" format="yyyy-MM-dd HH:mm"
|
||||||
|
v-model="addData.endTime"
|
||||||
|
@on-change="(e)=>{ addData.endTime = e }"
|
||||||
|
:placeholder="$L('请选择结束时间')"
|
||||||
|
style="width: 100%"
|
||||||
|
></DatePicker>
|
||||||
|
</FormItem>
|
||||||
|
<FormItem prop="description" :label="$L('事由')">
|
||||||
|
<Input type="textarea" v-model="addData.description"></Input>
|
||||||
|
</FormItem>
|
||||||
|
</Form>
|
||||||
|
<div slot="footer" class="adaption">
|
||||||
|
<Button type="default" @click="addShow=false">{{$L('取消')}}</Button>
|
||||||
|
<Button type="primary" :loading="loadIng > 0" @click="onInitiate">{{$L('确认')}}</Button>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import list from "./list.vue";
|
import list from "./list.vue";
|
||||||
import listDetails from "./details.vue";
|
import listDetails from "./details.vue";
|
||||||
|
import DrawerOverlay from "../../../components/DrawerOverlay";
|
||||||
export default {
|
export default {
|
||||||
components:{list,listDetails},
|
components:{list,listDetails,DrawerOverlay},
|
||||||
name: "review",
|
name: "review",
|
||||||
data(){
|
data(){
|
||||||
return{
|
return{
|
||||||
timeChose:this.$L('所有时间'),
|
procdefList: [],
|
||||||
|
|
||||||
list: [],
|
|
||||||
page: 1,
|
page: 1,
|
||||||
pageSize: 250,
|
pageSize: 250,
|
||||||
total: 0,
|
total: 0,
|
||||||
noText: '',
|
noText: '',
|
||||||
loadIng:false,
|
loadIng:false,
|
||||||
|
|
||||||
|
|
||||||
tabsValue:"",
|
tabsValue:"",
|
||||||
//
|
//
|
||||||
@ -135,7 +172,7 @@ export default {
|
|||||||
approvalList:[
|
approvalList:[
|
||||||
{value:"all",label:"全部审批"},
|
{value:"all",label:"全部审批"},
|
||||||
{value:"请假",label:"请假"},
|
{value:"请假",label:"请假"},
|
||||||
{value:"加班",label:"加班"},
|
{value:"加班申请",label:"加班申请"},
|
||||||
],
|
],
|
||||||
searchState:"all",
|
searchState:"all",
|
||||||
searchStateList:[
|
searchStateList:[
|
||||||
@ -147,45 +184,48 @@ export default {
|
|||||||
{value:4,label:"已撤回"}
|
{value:4,label:"已撤回"}
|
||||||
],
|
],
|
||||||
//
|
//
|
||||||
|
backlogTotal:0,
|
||||||
backlogList: [],
|
backlogList: [],
|
||||||
doneList:[],
|
doneList:[],
|
||||||
notifyList:[],
|
notifyList:[],
|
||||||
initiatedList: [],
|
initiatedList: [],
|
||||||
details:{}
|
//
|
||||||
|
details:{},
|
||||||
|
detailsShow:false,
|
||||||
|
//
|
||||||
|
addTitle:'',
|
||||||
|
addShow:false,
|
||||||
|
addData: {
|
||||||
|
type: '',
|
||||||
|
startTime:"",
|
||||||
|
endTime:"",
|
||||||
|
},
|
||||||
|
addRule: {
|
||||||
|
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:["年假","事假","病假","调休","产假","陪产假","婚假","例假","丧假","哺乳假"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.tabsValue = "initiated"
|
this.tabsValue = "initiated"
|
||||||
this.tabsClick()
|
this.tabsClick()
|
||||||
|
this.getProcdef()
|
||||||
|
this.getBacklogList()
|
||||||
},
|
},
|
||||||
methods:{
|
methods:{
|
||||||
|
|
||||||
changeTime(e){
|
|
||||||
switch (e) {
|
|
||||||
case 'all':
|
|
||||||
this.timeChose = this.$L('所有时间');
|
|
||||||
return;
|
|
||||||
case '24':
|
|
||||||
this.timeChose = this.$L('最近24小时');
|
|
||||||
return;
|
|
||||||
case '7':
|
|
||||||
this.timeChose = this.$L('最近7天');
|
|
||||||
return;
|
|
||||||
case '30':
|
|
||||||
this.timeChose = this.$L('最近30天');
|
|
||||||
return;
|
|
||||||
case 'customize':
|
|
||||||
this.timeChose = this.$L('自定义时间');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// tab切换事件
|
// tab切换事件
|
||||||
tabsClick(val){
|
tabsClick(val){
|
||||||
this.tabsValue = val || this.tabsValue
|
this.tabsValue = val || this.tabsValue
|
||||||
// if(this.tabsValue == 'backlog'){
|
if(val!=""){
|
||||||
|
this.approvalType = this.searchState = "all"
|
||||||
|
}
|
||||||
|
if(this.tabsValue == 'backlog'){
|
||||||
this.getBacklogList();
|
this.getBacklogList();
|
||||||
// }
|
}
|
||||||
if(this.tabsValue == 'done'){
|
if(this.tabsValue == 'done'){
|
||||||
this.getDoneList();
|
this.getDoneList();
|
||||||
}
|
}
|
||||||
@ -204,7 +244,32 @@ export default {
|
|||||||
this.notifyList.map(h=>{ h._active = false; })
|
this.notifyList.map(h=>{ h._active = false; })
|
||||||
this.initiatedList.map(h=>{ h._active = false; })
|
this.initiatedList.map(h=>{ h._active = false; })
|
||||||
item._active = true;
|
item._active = true;
|
||||||
this.details = item
|
//
|
||||||
|
if( window.innerWidth < 425 ){
|
||||||
|
this.goForward({name: 'manage-review-details', query: { id: item.id } });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if( window.innerWidth < 1010 ){
|
||||||
|
this.detailsShow = true;
|
||||||
|
}
|
||||||
|
this.details = {}
|
||||||
|
this.$nextTick(()=>{
|
||||||
|
this.details = item
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取列表数据
|
||||||
|
getProcdef(){
|
||||||
|
this.$store.dispatch("call", {
|
||||||
|
url: 'workflow/procdef/all',
|
||||||
|
method: 'post',
|
||||||
|
}).then(({data}) => {
|
||||||
|
this.procdefList = data.rows || [];
|
||||||
|
}).catch(({msg}) => {
|
||||||
|
$A.modalError(msg);
|
||||||
|
}).finally(_ => {
|
||||||
|
this.loadIng--;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// 获取待办列表
|
// 获取待办列表
|
||||||
@ -215,12 +280,16 @@ export default {
|
|||||||
data: {
|
data: {
|
||||||
page:this.page,
|
page:this.page,
|
||||||
page_size: this.pageSize,
|
page_size: this.pageSize,
|
||||||
|
proc_def_name: this.approvalType == 'all' ? '' : this.approvalType,
|
||||||
}
|
}
|
||||||
}).then(({data}) => {
|
}).then(({data}) => {
|
||||||
this.backlogList = data.rows.map((h,index)=>{
|
this.backlogList = data.rows.map((h,index)=>{
|
||||||
h._active = index == 0;
|
h._active = index == 0;
|
||||||
return h;
|
return h;
|
||||||
})
|
})
|
||||||
|
if(this.approvalType == 'all'){
|
||||||
|
this.backlogTotal = this.backlogList.length
|
||||||
|
}
|
||||||
if(this.tabsValue == 'backlog'){
|
if(this.tabsValue == 'backlog'){
|
||||||
this.$nextTick(()=>{
|
this.$nextTick(()=>{
|
||||||
this.details = this.backlogList[0] || {}
|
this.details = this.backlogList[0] || {}
|
||||||
@ -241,6 +310,7 @@ export default {
|
|||||||
data: {
|
data: {
|
||||||
page:this.page,
|
page:this.page,
|
||||||
page_size: this.pageSize,
|
page_size: this.pageSize,
|
||||||
|
proc_def_name: this.approvalType == 'all' ? '' : this.approvalType,
|
||||||
}
|
}
|
||||||
}).then(({data}) => {
|
}).then(({data}) => {
|
||||||
this.doneList = data.rows.map((h,index)=>{
|
this.doneList = data.rows.map((h,index)=>{
|
||||||
@ -267,6 +337,7 @@ export default {
|
|||||||
data: {
|
data: {
|
||||||
page:this.page,
|
page:this.page,
|
||||||
page_size: this.pageSize,
|
page_size: this.pageSize,
|
||||||
|
proc_def_name: this.approvalType == 'all' ? '' : this.approvalType,
|
||||||
}
|
}
|
||||||
}).then(({data}) => {
|
}).then(({data}) => {
|
||||||
this.notifyList = data.rows.map((h,index)=>{
|
this.notifyList = data.rows.map((h,index)=>{
|
||||||
@ -288,11 +359,13 @@ export default {
|
|||||||
// 获取我发起的
|
// 获取我发起的
|
||||||
getInitiatedList(){
|
getInitiatedList(){
|
||||||
this.$store.dispatch("call", {
|
this.$store.dispatch("call", {
|
||||||
method: 'get',
|
method: 'post',
|
||||||
url: 'workflow/process/startByMyself',
|
url: 'workflow/process/startByMyselfAll',
|
||||||
data: {
|
data: {
|
||||||
page:this.page,
|
page: this.page,
|
||||||
page_size: this.pageSize,
|
page_size: this.pageSize,
|
||||||
|
proc_def_name: this.approvalType == 'all' ? '' : this.approvalType,
|
||||||
|
state: this.searchState == 'all' ? '' : this.searchState
|
||||||
}
|
}
|
||||||
}).then(({data}) => {
|
}).then(({data}) => {
|
||||||
this.initiatedList = data.rows.map((h,index)=>{
|
this.initiatedList = data.rows.map((h,index)=>{
|
||||||
@ -309,6 +382,39 @@ export default {
|
|||||||
}).finally(_ => {
|
}).finally(_ => {
|
||||||
this.loadIng--;
|
this.loadIng--;
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 发起
|
||||||
|
initiate(item){
|
||||||
|
this.addTitle = item.name;
|
||||||
|
this.addShow = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
// 提交发起
|
||||||
|
onInitiate(){
|
||||||
|
this.$refs.initiateRef.validate((valid) => {
|
||||||
|
if (valid) {
|
||||||
|
this.loadIng++;
|
||||||
|
this.$store.dispatch("call", {
|
||||||
|
url: 'workflow/process/start',
|
||||||
|
data: {
|
||||||
|
proc_name:this.addTitle,
|
||||||
|
department_id:1,
|
||||||
|
var: JSON.stringify(this.addData)
|
||||||
|
},
|
||||||
|
method: 'post',
|
||||||
|
}).then(({data, msg}) => {
|
||||||
|
$A.messageSuccess(msg);
|
||||||
|
this.addShow = false;
|
||||||
|
this.$refs.initiateRef.resetFields();
|
||||||
|
this.tabsClick();
|
||||||
|
}).catch(({msg}) => {
|
||||||
|
$A.modalError(msg);
|
||||||
|
}).finally(_ => {
|
||||||
|
this.loadIng--;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
5
resources/assets/js/routes.js
vendored
5
resources/assets/js/routes.js
vendored
@ -34,6 +34,11 @@ export default [
|
|||||||
path: 'review',
|
path: 'review',
|
||||||
component: () => import('./pages/manage/review/index.vue'),
|
component: () => import('./pages/manage/review/index.vue'),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'manage-review-details',
|
||||||
|
path: 'review/details',
|
||||||
|
component: () => import('./pages/manage/review/details.vue'),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'manage-setting',
|
name: 'manage-setting',
|
||||||
path: 'setting',
|
path: 'setting',
|
||||||
|
|||||||
260
resources/assets/sass/pages/page-review.scss
vendored
260
resources/assets/sass/pages/page-review.scss
vendored
@ -51,13 +51,15 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
max-width: 360px;
|
|
||||||
width: 100%;
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
bottom: 12px;
|
bottom: 12px;
|
||||||
|
max-width: 360px;
|
||||||
|
width: 100%;
|
||||||
|
@media (max-width: 1010px) {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
.review-main-list{
|
.review-main-list{
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -121,132 +123,136 @@
|
|||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
display: flex;
|
display: flex;
|
||||||
margin: 0 0 12px 12px;
|
margin: 0 0 12px 12px;
|
||||||
.review-details{
|
@media (max-width: 1010px) {
|
||||||
flex: 1 1 auto;
|
display: none;
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
border-radius: 8px;
|
|
||||||
border: 1px solid #eeeeee;
|
|
||||||
.review-details-box{
|
|
||||||
flex: 1 1 auto;
|
|
||||||
padding: 24px;
|
|
||||||
overflow-y: scroll;
|
|
||||||
.review-details-title{
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
.ivu-tag{
|
|
||||||
margin-left: 8px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.review-details-subtitle{
|
|
||||||
margin-top: 8px;
|
|
||||||
display: flex;
|
|
||||||
.ivu-avatar{
|
|
||||||
margin-right: 8px;
|
|
||||||
}
|
|
||||||
> span{
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.timeline-title{
|
|
||||||
font-weight: bold;
|
|
||||||
padding-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.review-process-name{
|
|
||||||
margin-bottom: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.review-process-state{
|
|
||||||
font-size: 12px;
|
|
||||||
color: #19be6b;
|
|
||||||
}
|
|
||||||
|
|
||||||
.review-process-right{
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.review-details-text{
|
|
||||||
margin-bottom: 12px;
|
|
||||||
> h4{
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
> p{
|
|
||||||
font-size: 14px;
|
|
||||||
margin-top: 2px;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.review-details-text:nth-last-child(1){
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
.review-details-process{
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
margin-top: 16px;
|
|
||||||
position: relative;
|
|
||||||
.review-details-line{
|
|
||||||
position: absolute;
|
|
||||||
left: 23px;
|
|
||||||
top: 5px;
|
|
||||||
bottom: 5px;
|
|
||||||
width: 3px;
|
|
||||||
background: #19be6b;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
.review-process{
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
position: relative;
|
|
||||||
z-index: 2;
|
|
||||||
margin-bottom: 32px;
|
|
||||||
.review-process-left{
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
.review-process-text{
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
margin-left: 8px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.review-process:nth-last-child(1){
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.review-copy{
|
|
||||||
margin-top: 8px;
|
|
||||||
display: flex;
|
|
||||||
.review-copy-member{
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
background: #F4F4F5;
|
|
||||||
padding:2px 8px;
|
|
||||||
border-radius: 20px;
|
|
||||||
.ivu-avatar{
|
|
||||||
margin-right: 4px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.review-details-box::-webkit-scrollbar {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.review-operation{
|
|
||||||
flex: 0 0 auto;
|
|
||||||
height: 60px;
|
|
||||||
padding: 0 24px;
|
|
||||||
border-top: 1px solid #F4F4F5;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 10px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.review-details{
|
||||||
|
flex: 1 1 auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid #eeeeee;
|
||||||
|
background: #fff;
|
||||||
|
.review-details-box{
|
||||||
|
flex: 1 1 auto;
|
||||||
|
padding: 24px;
|
||||||
|
overflow-y: scroll;
|
||||||
|
.review-details-title{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
.ivu-tag{
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.review-details-subtitle{
|
||||||
|
margin-top: 8px;
|
||||||
|
display: flex;
|
||||||
|
.ivu-avatar{
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
> span{
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-title{
|
||||||
|
font-weight: bold;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// .review-process-name{
|
||||||
|
// margin-bottom: 4px;
|
||||||
|
// }
|
||||||
|
|
||||||
|
.review-process-state{
|
||||||
|
font-size: 12px;
|
||||||
|
color: #19be6b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-process-right{
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.review-details-text{
|
||||||
|
margin-bottom: 12px;
|
||||||
|
> h4{
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
> p{
|
||||||
|
font-size: 14px;
|
||||||
|
margin-top: 2px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.review-details-text:nth-last-child(1){
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
.review-details-process{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-top: 16px;
|
||||||
|
position: relative;
|
||||||
|
.review-details-line{
|
||||||
|
position: absolute;
|
||||||
|
left: 23px;
|
||||||
|
top: 5px;
|
||||||
|
bottom: 5px;
|
||||||
|
width: 3px;
|
||||||
|
background: #19be6b;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
.review-process{
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
margin-bottom: 32px;
|
||||||
|
.review-process-left{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
.review-process-text{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.review-process:nth-last-child(1){
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.review-copy{
|
||||||
|
margin-top: 8px;
|
||||||
|
display: flex;
|
||||||
|
.review-copy-member{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
background: #F4F4F5;
|
||||||
|
padding:2px 8px;
|
||||||
|
border-radius: 20px;
|
||||||
|
.ivu-avatar{
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.review-details-box::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.review-operation{
|
||||||
|
flex: 0 0 auto;
|
||||||
|
height: 55px;
|
||||||
|
padding: 0 24px;
|
||||||
|
border-top: 1px solid #F4F4F5;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user