OA/pages/views/leave_request.vue

537 lines
15 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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>