You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

316 lines
8.1 KiB

<template>
<view class="header">
<view class="flex between top v-center">
<view class="flex v-center">
<fui-icon name="arrowleft" color="#fff" :size="50" @tap="goBack"></fui-icon>
<view>
<text class="label mr-6">受理编号</text>
<text>{{ mailId }}</text>
</view>
</view>
<view>
<m-button class="flex v-center gap-4" :type="isFav? 'danger' :'primary'" @tap="handleFav">
<fui-icon name="star" color="#fff" :size="30"></fui-icon>
<text>收藏</text>
</m-button>
</view>
</view>
<Steps />
<view class="timer" v-if="!mail.flowRemainingTime || mail.flowRemainingTime >= 0">
<view class="flex between mb-8">
<text>剩余处理时间</text>
<text>{{ formatTimeText(mail.flowRemainingTime) }}</text>
</view>
<m-progress :percentage="mail.flowRemainingTimePercentage" />
</view>
<view class="timer-danger flex between" v-else>
<text>超时</text>
<text>{{ formatTimeText(mail.flowRemainingTime) }}</text>
</view>
</view>
<view class="body">
<fui-tabs :tabs="tabs" :short="false" @change="changeTab" :current="tabCurrent"></fui-tabs>
<view style="height: calc(100% - 48px); overflow: auto;">
<component v-for="item in tabs" :is="components[item.template]" v-model="requestData" v-show="view === item.template" ref="templatesRef"></component>
</view>
</view>
<view class="footer flex end gap">
<template v-if="workId">
<template v-for="item in actions" >
<m-button size="large" :type="item.btnType" :plain="item.btnPlain" @tap="handleNext(item.key)" v-if="handleBtnShow(item.key)">{{ item.btnLabel }}</m-button>
</template>
</template>
</view>
<m-popup ref="approvalPopup" title="提交审批" placeholder="请输入审批意见" confirmText="审批通过" @confirm="sumbitApproval" />
<m-popup ref="mail110RejectPopup" title="不纳入信件" placeholder="请输入不纳入信件理由" confirmText="提交" @confirm="mail110Reject" />
<approval ref="approvalRef" v-model="requestData" @submit="(key) => handleNext(key)" />
<completion ref="completionRef" v-model="requestData" @submit="(key) => handleNext(key)" />
<MailReturn ref="mailReturnRef" v-model="requestData" @submit="(key) => handleNext(key)" />
</template>
<script setup>
import Steps from './components/steps.vue'
import approval from './components/approval.vue'
import MailReturn from './components/mail-return.vue'
import completion from './components/completion.vue'
import MainContactInfo from './templates/MainContactInfo.vue'
import MailTypeForm from './templates/MailTypeForm.vue'
import Flows from './templates/Flows.vue'
import DeptSelectForm from './templates/DeptSelectForm.vue'
import ApprovalOpinions from './templates/ApprovalOpinions.vue'
import ContactWriter from './templates/ContactWriter.vue'
import { onMounted } from "vue"
const components = {
'MainContactInfo': MainContactInfo,
'MailTypeForm': MailTypeForm,
'DeptSelectForm': DeptSelectForm,
'Flows': Flows,
'ApprovalOpinions': ApprovalOpinions,
'ContactWriter': ContactWriter
}
import { ref, watch, provide, defineProps } from 'vue'
import { workDetail } from '@/api/work'
import { flowNext, mailDetail } from '@/api/mail'
import { addFav, delFav } from '@/api/fav'
import { getTabs } from './action'
import { formatTimeText } from '@/common/util'
import store from '@/store'
const tabs = ref([
{
name: '信件信息',
template: 'MainContactInfo'
}
]);
const tabCurrent = ref(0)
const view = ref('MainContactInfo')
function changeTab(item) {
view.value = item.template
tabCurrent.value = item.index
}
function goBack() {
uni.navigateBack({
delta: 1
});
}
const props = defineProps({
mailId: {
type: String
},
workId: {
type: String
}
})
const mail = ref({})
const flows = ref([])
const flowNode = ref({})
const actions = ref([])
const approvals = ref([])
const mailReturns = ref([])
const isFav = ref(false)
watch(() => flowNode.value.key, (val) => {
tabs.value = getTabs(val)
})
async function getDetail() {
let data;
uni.showLoading({
title: '加载中'
});
if (props.workId) {
data = await workDetail({
mailId: props.mailId,
workId: props.workId
})
} else {
data = await mailDetail(props.mailId)
}
uni.hideLoading();
mail.value = data.mail
flowNode.value = data.flowNode
flows.value = data.flows
actions.value = data.actions
if (data.approvals) {
data.approvals.reverse()
}
approvals.value = data.approvals || [];
mailReturns.value = data.mailReturns
isFav.value = data.isFav
}
getDetail();
provide('mail', mail);
provide('flows', flows);
provide('approvals', approvals);
provide('mailReturns', mailReturns);
provide('flowNode', flowNode);
const templatesRef = ref()
const requestData = ref({})
const approvalPopup = ref()
const approvalRef = ref()
const completionRef = ref()
const mailReturnRef = ref()
const mail110RejectPopup = ref()
// 是否显示该按钮
function handleBtnShow(key) {
if (key === 'mail110Reject') {
return mail.value.source === '110_report_complaints';
}
const arr = ['reportLeader', 'applyExtension', 'applicationCompleted', 'save', 'interviewSave', 'initiateCountersign'];
return arr.indexOf(key) === -1;
}
async function handleNext(key) {
console.log(key)
if (key === 'mail110Reject') {
mail110RejectPopup.value.open()
return
}
// 退回
if (key === 'return') {
mailReturnRef.value.open()
return
}
// 审批
if (key === 'approved') {
if (isNeedLeaderApproval()) {
approvalRef.value.open()
} else {
approvalPopup.value.open()
}
return
}
// 认定办结
if (key === 'approvedCompletion') {
completionRef.value.open()
return
}
if (key !== 'returnSubmit' && key !== 'mail110RejectSubmit') {
for (let i = 0; i < templatesRef.value.length; i++) {
if (templatesRef.value[i].validate) {
try {
await templatesRef.value[i].validate()
} catch(e) {
tabCurrent.value = 1
console.log('tabCurrent.value', tabCurrent.value)
throw e
}
}
}
}
flowNext({
mailId: props.mailId,
nextActionKey: key,
flowKey: flowNode.value.key,
data: requestData.value
}).then(() => {
tabCurrent.value = 0
if (key === 'sign') {
if (requestData.value.mailFirstCategory === '无效类' || requestData.value.mailFirstCategory === '终止类' || requestData.value.mailFirstCategory === '感谢信类') {
uni.showToast({
title: '操作成功',
type: 'success',
duration: 3000
})
goBack()
return
}
uni.showToast({
title: '签收成功',
type: 'success',
duration: 3000
})
getDetail()
return
}
uni.showToast({
title: '操作成功',
type: 'success'
})
goBack()
})
}
function sumbitApproval(val) {
requestData.value.approvalComment = val
handleNext('approvedSubmit')
}
function mail110Reject(val) {
requestData.value.reason = val
handleNext('mail110RejectSubmit')
}
function isNeedLeaderApproval() {
return mail.value.completeMethod === 'online' && (flowNode.value.key === 'second_approval' || flowNode.value.key === 'second_deputy_approval')
}
async function handleFav() {
if (isFav.value) {
isFav.value = false
await delFav(props.mailId)
} else {
isFav.value = true
await addFav(props.mailId)
}
}
watch(() => mail.value.flowRemainingTime,(val) => {
if (val > -3600 && val < 3600 && store.state.isWorkingDay) {
setTimeout(() => {
mail.value.flowRemainingTime -= 1
}, 1000)
}
})
</script>
<style lang="scss" scoped>
.header {
padding-top: 40px;
font-size: 11px;
background-color: var(--primary-color);
color: #fff;
.top {
padding: 12px 8px;
font-size: 12px;
}
.timer {
padding: 12px;
}
.timer-danger {
background: linear-gradient( 180deg, #FF5C37 0%, #E03021 100%);
height: 45px;
line-height: 45px;
margin-top: 10px;
padding: 0 10px;
}
}
.body {
font-size: 11px;
background: #F1F1F1;
height: calc(100vh - 121px - 94px);
.fui-tabs__scrollbox {
border-bottom: 1px solid #E5E5E5;
}
}
.footer {
padding: 8px 12px;
background-color: #fff;
height: 32px;
border-top: 1px solid #e5e5e5;
}
</style>