OfficeApp/pages/views/leave_request.vue

537 lines
15 KiB
Vue
Raw Normal View History

2023-07-15 17:51:20 +08:00
<template>
<view class="leave_request">
<view class="leave_box">
<view class="leava_type flex_a_c">
<view class="title">请假类型</view>
<input type="text" v-model="leavaTypeVal" placeholder="请选择" disabled @click="leavaTypeShow = true">
</view>
<block v-for="(item,i) in timeData" :key="item.title">
<view class="cont_cell">
<view class="title">{{ item.title }}</view>
<input type="text" v-model="item.time" placeholder="请选择时间" disabled @click="selectTime(item)">
</view>
</block>
<view class="cont_cell">
<view class="title">请假工时</view>
<input type="text" v-model="manHour" disabled placeholder="请假工时">
</view>
<view class="cont_cell">
<view class="title">请假天数</view>
<input type="text" v-model="daysNum" disabled placeholder="请假天数">
</view>
<view class="cont_cell">
<view class="title">请假事由</view>
<input type="text" v-model="reason" placeholder="请输入请假事由">
</view>
<!-- 附件 -->
<block v-for="(item, i) in fileArray" :key="i">
<view class="file flex_a_c_j_sb">
<view class="l_file">
<view class="file_name">{{ item.name }}</view>
<view class="file_size">{{ item.filesize | formatBytes }}</view>
<view class="upload_people">上传人{{ item.admin_name }}</view>
</view>
<u-icon @click="delImg(i)" name="close-circle" color="#333333" size="28"></u-icon>
</view>
</block>
<view class="upload_box flex_a_c_j_sb" @click="seleckImage">
<view>
<view class="title">选择文件并上传</view>
<view class="text">
上传前请规范命名最大只能上传100M的文件<br />
超过请压缩成多个文件上传
</view>
</view>
<u-icon name="plus-circle" color="#333333" size="28"></u-icon>
</view>
</view>
<view class="flow_path">
<view class="cont_cell">
<view class="title">选择审批流程</view>
<input type="text" v-model="flowPath" placeholder="请选择" disabled @click="flowPathShow = true">
</view>
<view class="cont_cell">
<view class="title">审核人</view>
<input v-if="flowDate === false" type="text" v-model="auditor" placeholder="请选择" disabled
@click="branchShow = true">
<view v-else class="audit_process">
<view v-for="(item,i) in flowDate" :key="i" class="process_item flex">
<view class="circle"></view>
<view class="right">
<view v-if="item.flow_type==1">
{{i+1}}级审批
<view class="verifier">当前部门负责人</view>
</view>
<view v-else-if="item.flow_type==2">
{{i+1}}级审批
<view class="verifier">上级部门负责人</view>
</view>
<view v-else>
<view v-if="item.flow_type==3">
{{i+1}}级审批
<text class="tag">或签</text>
</view>
<view v-if="item.flow_type==4">
{{i+1}}级审批
<text class="tag">会签</text>
</view>
<view v-for="(info,b) in item.user_id_info" :key="b" class="verifier">
{{ info.name }}
</view>
</view>
</view>
</view>
</view>
</view>
<view class="cont_cell">
<view class="title">抄送人</view>
<input type="text" v-model="carbon" placeholder="请选择" disabled>
</view>
</view>
<view class="bot_btn">
<view class="reset" @click="reset">重置</view>
<view class="submit_btn" @click="submiteBtn">立即提交</view>
</view>
<u-picker :show="leavaTypeShow" keyName="name" :columns="columns" @cancel="leavaTypeShow = false"
@confirm="leavaType">
</u-picker>
<!-- 选择审批流程 -->
<u-action-sheet :actions="flowPathSheet" @select="flowPathSelect" title="选择审批流程" :show="flowPathShow"
@close="flowPathShow=false" :closeOnClickOverlay="true" :closeOnClickAction="true">
</u-action-sheet>
<!-- 部门选择 -->
<u-picker :show="branchShow" :defaultIndex=[0,0] ref="branchRef" :columns="branchColumns" @confirm="branchConfirm"
@change="branchHandler" :closeOnClickOverlay="true" @close="branchShow=false" keyName="name">
</u-picker>
<!-- 选择时间 -->
<block v-for="(item,i) in timeData" :key="i">
<u-datetime-picker :show="item.timeShow" v-model="item.timeVal" mode="datetime" :maxDate="1786778555000"
:minDate="timestamp" closeOnClickOverlay @confirm="timeConfirm($event,i)" @cancel="item.timeShow = false"
@close="item.timeShow = false"></u-datetime-picker>
</block>
</view>
</template>
<script>
import { getFlowAPI, getFlowUsersAPI, getDepartmentTreeAPI, getEmployeeAPI, PostApproveAddAPI } from '@/api/oaApi.js'
import { oaLeaveData } from '@/static/server/server.js'
import { oaUploads } from '../../api/upload'
import { Toast } from '../../libs/uniApi'
export default {
data() {
return {
timestamp: '', // 当前时间
flowPath: '', // 审批流程
flow_id: '', // 审批流程id
auditor: '', // 审核人
carbon: '', // 抄送人
copy_uids: '', // 抄送人id
manHour: '', // 请假工时
daysNum: '', // 请假天数
reason: '', // 请假事由
flowPathShow: false,
flowPathSheet: [],
timeData: [{
title: '开始时间:',
timeShow: false,
timeVal: '', // 时间戳
time: '', // 完整时间
timeDay: '', // 年月日
timeHour: '', // 时分秒
},
{
title: '结束时间:',
timeShow: false,
timeVal: '', // 时间戳
time: '', // 完整时间
timeDay: '', // 年月日
timeHour: '', // 时分秒
}
],
leavaTypeShow: false,
leavaTypeVal: '',
leavaTypeId: '',
columns: [oaLeaveData],
// 部门选择 二级联动
branchShow: false,
branchColumns: [],
isflowDate: true,
flowDate: [],
fileArray: []
}
},
onLoad() {},
onShow() {
this.getFlow()
// 获取当前时间戳
this.timestamp = Date.parse(new Date());
},
watch: {
timeData: {
handler(newVal, oldVal) {
if (newVal[0].time.length > 0 && newVal[1].time.length > 0) {
const { leaveDays, leaveHours } = this.calculateLeaveDaysAndHours(this.timeData[0].time, this.timeData[1]
.time)
this.manHour = leaveHours + '小时'
this.daysNum = leaveDays + '天'
}
},
deep: true
}
},
methods: {
selectTime(item) {
item.timeShow = true
},
async branchHandler(e) {
const {
columnIndex,
value,
values, // values为当前变化列的数组内容
index,
// 微信小程序无法将picker实例传出来只能通过ref操作
picker = this.$refs.branchRef
} = e
// 当第一列值发生变化时,变化第二列(后一列)对应的选项
if (columnIndex === 0) {
// picker为选择器this实例变化第二列对应的选项
let res = await getEmployeeAPI({ did: value[0].id })
if (res.length < 1) {
res[0] = { name: '无' }
}
picker.setColumnValues(1, res)
}
},
// 回调参数为包含columnIndex、value、values
branchConfirm(e) {
console.log('confirm', e)
this.auditor = e.value[1].name
this.branchShow = false
},
/** 请假类型 */
leavaType(e) {
this.leavaTypeVal = e.value[0].name
this.leavaTypeId = e.value[0].id
this.leavaTypeShow = false
},
/** 选择审核人 */
async getFlowUsers(id) {
const flowUsers = await getFlowUsersAPI({ id: id })
console.log(flowUsers.data);
this.flowDate = flowUsers.data.flow_data
// 主管及以上请假审批
if (!flowUsers.data.flow_data) {
const tree = await getDepartmentTreeAPI()
const picker = this.$refs.branchRef
picker.setColumnValues(0, tree[0].children)
let res = await getEmployeeAPI({ did: tree[0].children[0].id })
picker.setColumnValues(1, res)
this.carbon = ''
} else {
this.carbon = flowUsers.data.copy_unames
this.copy_uids = flowUsers.data.copy_uids
}
},
flowPathSelect(value) {
this.flowPath = value.name
this.flow_id = value.id
this.getFlowUsers(value.id)
},
async getFlow() {
const flow = await getFlowAPI({ type: 1, flow_cate: 1 })
this.flowPathSheet = flow
},
timeConfirm(e, i) {
this.timeData[i].time = uni.$u.timeFormat(e.value, 'yyyy-mm-dd hh:MM:ss')
this.timeData[i].timeDay = uni.$u.timeFormat(e.value, 'yyyy-mm-dd')
this.timeData[i].timeHour = uni.$u.timeFormat(e.value, 'hh:MM')
this.timeData[i].timeShow = false
},
async submiteBtn() {
let fileIds = [];
this.fileArray.map((item, i) => {
fileIds.push(item.id)
});
let subData = {
detail_type: this.leavaTypeId,
end_time_a: this.timeData[1].timeDay,
end_time_b: this.timeData[1].timeHour,
start_time_a: this.timeData[0].timeDay,
start_time_b: this.timeData[0].timeHour,
duration: this.manHour,
content: this.reason,
flow_id: this.flow_id,
file_ids: fileIds.join(','),
copy_names: this.carbon,
copy_uids: this.copy_uids,
type: '1',
id: 0
}
try {
const res = await PostApproveAddAPI(subData)
Toast('提交成功')
} catch (e) {
Toast('提交失败')
}
},
reset() {
this.flowPath = ''
this.flowDate = []
this.leavaTypeVal = ''
this.leavaTypeId = ''
this.daysNum = ''
this.timeData[0].time = ''
this.timeData[0].time = ''
this.timeData[1].time = ''
this.timeData[1].time = ''
this.manHour = ''
this.reason = ''
this.flow_id = ''
this.carbon = ''
this.copy_uids = ''
},
seleckImage(i) {
let that = this
uni.chooseImage({
count: 1,
sizeType: ['original', 'compressed'],
sourceType: ['album', 'camera'],
success: function(res) {
that.loading = true
let objImg = {}
objImg.filesize = res.tempFiles[0].size
objImg.admin_name = '马开明'
oaUploads(res.tempFilePaths[0], 'img').then(res => {
objImg.name = res.filename
that.fileArray.push(res)
that.loading = false
Toast('上传成功')
}).catch(err => {
Toast('上传失败')
that.loading = false
console.log('上传失败', err)
})
},
fail: function(err) {
Toast('添加失败')
console.log('失败', err)
}
});
},
delImg(i) {
let that = this
uni.showModal({
title: '删除图片',
content: '确定删除图片?',
success: res => {
if (res.confirm) {
that.fileArray.splice((i, 1))
} else if (res.cancel) {
console.log('用户点击取消');
}
}
})
},
/**
* 计算两个时间戳之间相差的小时数
* */
calculateLeaveDaysAndHours(leaveStartTime, leaveEndTime, hoursPerDay = 8) {
const startDate = new Date(leaveStartTime);
const endDate = new Date(leaveEndTime);
// 计算请假天数
const leaveDays = Math.floor((endDate.getTime() - startDate.getTime()) / (24 * 60 * 60 * 1000)) + 1;
// 计算请假总小时数
const leaveHours = leaveDays * hoursPerDay;
// 返回结果
return {
leaveDays,
leaveHours,
};
}
},
filters: {
// 数字转MB
formatBytes(bytes, decimals = 2) {
if (bytes === 0) return '0 MB';
const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(decimals)) + ' ' + sizes[i];
}
},
onPullDownRefresh() {
uni.stopPullDownRefresh()
}
}
</script>
<style lang="scss">
.leave_request {
position: relative;
padding-bottom: 100px;
}
.leave_box,
.flow_path {
width: 100%;
padding: 0 28.07rpx;
background: #fff;
margin-bottom: 35.09rpx;
padding-bottom: 28.07rpx;
}
.bot_btn {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
height: 87.72rpx;
>view {
width: 50%;
text-align: center;
line-height: 87.72rpx;
}
.reset {
background-color: #fff;
}
.submit_btn {
color: #fff;
height: 87.72rpx;
background: $theme-oa-color;
}
}
.leava_type {
height: 100rpx;
border-bottom: 1px solid #999;
.title {
font-size: 31.58rpx;
}
}
.cont_cell {
display: flex;
align-items: center;
width: 100%;
min-height: 87.72rpx;
border-bottom: 1px solid #f7f7f7;
.title {
font-size: 31.58rpx;
}
}
// 审批流程
.audit_process {
.process_item {
position: relative;
height: 100%;
margin: 17.54rpx 0;
}
:last-child {
.circle {
&::before {
display: none;
}
}
}
.tag {
font-size: 21.05rpx;
color: #fff;
padding: 0 4px;
margin-left: 10.53rpx;
background-color: #3c9cff;
border-radius: 2px;
}
.verifier {
margin: 17.54rpx 0;
}
}
.circle {
width: 31.58rpx;
height: 31.58rpx;
background-color: #fff;
border: 2px solid #34A853;
border-radius: 50%;
margin: 0 5px;
display: flex;
flex-direction: column;
align-items: center;
&::before {
content: "";
display: block;
position: absolute;
clear: both;
width: 1px;
height: 100%;
background-color: rgba(204, 204, 204, 0.5);
margin: 31.58rpx;
}
}
// 附件
.upload_box {
padding: 17.54rpx;
background-color: #F7F7F7;
border-radius: 4px;
.title {
font-size: 28.07rpx;
}
.text {
margin-top: 7.02rpx;
font-size: 21.05rpx;
color: #999;
}
}
.file_name {
width: 526.32rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.file {
padding: 17.54rpx;
border-radius: 4px;
border: 1px solid #F2F2F2;
margin: 17.54rpx 0;
.file_size {
margin-top: 7.02rpx;
}
.file_size,
.upload_people {
font-size: 21.05rpx;
color: #999;
}
}
</style>