OA/pages/leave_request/index.vue

1012 lines
24 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="" v-for='(fieldValue, fieldKey) in dataobj' :key="fieldKey">
<!-- {{fieldKey}} -->
<!-- {{ fieldValue.title }} - {{ fieldValue.type }} -->
<view class="leava_type flex_a_c"
v-if="fieldValue.type=='select'&&fieldKey!='copy_uids'&&fieldKey!='check_admin_ids'&&fieldKey!='flow_id'&&fieldKey!='name'">
<view class="title">{{fieldValue.title}}</view>
<!-- {{fieldKey}} -->
<input type="text" v-model="meatelist[fieldKey]" placeholder="请选择" @click="leixin(fieldKey)">
</view>
<view class="leava_type flex_a_c" v-if="fieldKey=='name'&&typeId!=24">
<view class="title">{{fieldValue.title}}</view>
<input type="text" v-model="meatelist[fieldKey]" placeholder="请选择" @click="leixiner()">
</view>
<view class=""
v-if="fieldValue.type=='input'&&fieldKey!='end_time'&&fieldKey!='start_time'&&fieldKey!='duration'">
<view class="cont_cell">
<view class="title">{{fieldValue.title}}</view>
<input type="text" v-model="meatelist[fieldKey]" :placeholder="fieldValue.title">
</view>
</view>
<view class="" v-if=" fieldKey=='start_time'">
<view class="cont_cell">
<view class="title">{{ timeData[0].title }}</view>
<input type="text" v-model="timeData[0].time" placeholder="请选择时间" disabled
@click="selectTime(timeData[0])">
</view>
</view>
<view class="" v-if="fieldKey=='end_time'">
<view class="cont_cell">
<view class="title">{{ timeData[1].title }}</view>
<input type="text" v-model="timeData[1].time" placeholder="请选择时间" disabled
@click="selectTime(timeData[1])">
</view>
</view>
<view class="" v-if="fieldKey=='duration'">
<view class="cont_cell">
<view class="title">{{fieldValue.title}}</view>
<input type="text" v-model="manHour" disabled placeholder="请假工时">
</view>
</view>
<view class="" v-if="fieldValue.type=='textarea'">
<view class="cont_cell">
<view class="title">{{fieldValue.title}}</view>
<input type="text" v-model="meatelist[fieldKey]" :placeholder="fieldValue.title">
</view>
</view>
<view class="" v-if="fieldValue.type=='file'">
<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="" v-for="(itemValue, itemKey) in fieldValue.item" :key="itemKey">
{{ itemKey }}: {{ itemValue }}
</view> -->
</view>
</view>
<view class="cont_details">
<view class="examine">审批流程</view>
<view class="cont_cell">
<view class="title" >审核状态:</view>
{{dataobj1.detail.check_status=='0'?'待审核':dataobj1.detail.check_status=='1'?'审核中':dataobj1.detail.check_status=='2'?'审核通过':dataobj1.detail.check_status=='3'?'审核不通过':'撤销审核'}}
</view>
<view class="cont_cell">
<view class="title">当前审核人:</view>
<input type="text" v-model="dataobj1.detail.check_user" disabled placeholder="请假工时">
</view>
<view class="cont_cell">
<view class="title">抄送人:</view>
<input type="text" v-model="dataobj1.detail.copy_user" disabled placeholder="请假工时">
</view>
<view class="examine">审批记录</view>
<block v-for="(item,i) in check_record" :key="i">
<view class="record" style="display: flex;">
<view class="circle"></view>
<text class="text">{{item.check_time_str}} {{item.name}} {{item.status_str}}
了此申请操作意见{{item.content}}</text>
</view>
</block>
</view>
<view class="flow_path">
<radio-group class="select_group" @change="deliveryWayChangetwo">
<label class="radio_select" style="margin-right:15rpx;display: flex; margin-bottom: 30rpx;">
<view style="margin-right:5rpx;">
<radio value="1" />
</view>
审核结束
</label>
<label class="radio_select" style="margin-right:15rpx;display: flex;">
<view style="margin-right:5rpx;">
<radio value="2" />
</view>
<view @click="branchShow = true" style="display: flex;">
<view class="title"> 下一位审批人</view>
<input type="text" v-model="check_admin_name" placeholder="请选择" disabled>
</view>
</label>
</radio-group>
<!-- <view class="cont_cell" @click="branchShow1 = true">
<view class="title">抄送人:</view>
<input type="text" v-model="copy_names" placeholder="请选择" disabled>
</view> -->
<view class="cont_cell" style="padding-top: 20rpx;">
<view class="title" style="width: 200rpx;">审核意见</view>
<textarea v-model="mscontent" placeholder="请输入审核意见" />
</view>
</view>
<view class="bot_btn">
<view class="reset" @click="appflowcheck()">拒绝</view>
<view class="submit_btn" @click=" appflowcheck1()">通过</view>
</view>
<u-picker :show="branchShow" :defaultIndex='defaultIndex' ref="branchRef" :columns="branchColumns"
@confirm="branchConfirm" @change="columnCode" :closeOnClickOverlay="true" @close="branchShowclose"
keyName="name">
</u-picker>
</view>
</template>
<script>
import {
oaLeaveData
} from '@/static/server/server.js'
import {
oaUploads
} from '../../api/upload'
import {
Toast
} from '../../libs/uniApi'
import {
appfield,
getemployee,
userdepartment,
appapprove,
appapproveview,
appflow_check,
} from '@/api/oa.js'
export default {
data() {
return {
meatelist: {
},
defaultIndex: [0, 0, 0],
defaultIndex1: [0, 0, 0],
defaultIndex2: [0, 0, 0],
dataobj: {},
timestamp: '', // 当前时间
flowPath: '', // 审批流程
flow_id: '', // 审批流程id
check_admin_name: '', // 审核人
check_admin_ids: [],
copy_names: '', // 抄送人
copy_uids: '', // 抄送人id
manHour: '', // 请假工时
daysNum: '', // 请假天数
content: '', // 请假事由
flowPathShow: false,
flowPathSheet: [],
check: "",
mscontent: "",
timeData: [{
title: '开始时间:',
timeShow: false,
timeVal: '', // 时间戳
time: '', // 完整时间
timeDay: '', // 年月日
timeHour: '', // 时分秒
},
{
title: '结束时间:',
timeShow: false,
timeVal: '', // 时间戳
time: '', // 完整时间
timeDay: '', // 年月日
timeHour: '', // 时分秒
}
],
leavaTypeShow: false,
leavaTypeVal: '',
leavaTypeId: '',
leavaTypeId1: '',
leavaTypeId2: '',
columns: [],
// 部门选择 三级级联动
branchShow: false,
branchShow1: false,
branchShow2: false,
branchColumns: [],
branchColumns1: [],
branchColumns2: [],
isflowDate: true,
flowDate: [],
fileArray: [],
typeId: '',
flag1: false,
datatype: '',
dataobj1: {},
check_record: []
}
},
onLoad(option) {
this.typeId = option.type
if (option.type == 8) {
this.timeData[0].title = '借用日期:'
this.timeData[1].title = '拟归还日期:'
}
this.applist(option.type)
this.getDocumentList()
this.getDocumentList2()
},
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: {
async getDocumentList2() {
this.columns3 = []
const res = await userdepartment({
tree: 1
})
const deArr = res.data
this.columns3.push(deArr)
},
confirm(e) {
console.log(e)
this.flag1 = false
},
async applist(type) {
let res = await appapproveview({
id: type
})
console.log(res.data)
this.dataobj1 = res.data
this.check_record = res.data.check_record
this.applist1(res.data.detail.type)
// this.dataobj = res.data.field
// console.log(this.dataobj)
},
async applist1(type) {
let res = await appfield({
type: type
})
this.dataobj = res.data.field
this.meatelist.name = 'name' in this.dataobj1.detail ? this.dataobj1.detail.name : ''
this.timeData[0].time = 'start_time' in this.dataobj1.detail ? this.dataobj1.detail.start_time : ''
this.timeData[1].time = 'end_time' in this.dataobj1.detail ? this.dataobj1.detail.end_time : ''
this.meatelist.mobile = 'mobile' in this.dataobj1.detail ? this.dataobj1.detail.mobile : ''
this.meatelist.department_type = 'department_type' in this.dataobj1.detail ? this.dataobj1.detail
.department_type_title : ''
this.meatelist.detail_type = 'detail_type' in this.dataobj1.detail ? this.dataobj1.detail
.detail_type_title : ''
this.meatelist.other_type = 'other_type' in this.dataobj1.detail ? this.dataobj1.detail
.other_type_title : ''
this.meatelist.remark = 'remark' in this.dataobj1.detail ? this.dataobj1.detail.remark : ''
this.meatelist.remark1 = 'remark1' in this.dataobj1.detail ? this.dataobj1.detail.remark1 : ''
this.meatelist.address = 'address' in this.dataobj1.detail ? this.dataobj1.detail.address : ''
this.meatelist.detail_time = 'detail_time' in this.dataobj1.detail ? this.dataobj1.detail.detail_time :
''
this.meatelist.content = 'content' in this.dataobj1.detail ? this.dataobj1.detail.content : ''
// this.meatelist.remark1 = 'remark1' in this.dataobj1.detail ? this.dataobj1.detail.remark1 : ''
// this.meatelist.remark1 = 'remark1' in this.dataobj1.detail ? this.dataobj1.detail.remark1 : ''
if ('detail_type' in this.dataobj1.detail) {
const detailTypeOptions = Object.entries(this.dataobj.detail_type.item).map(([id, name]) => ({
id,
name
}));
this.columns = detailTypeOptions
for (let i in this.columns) {
if (this.columns[i].id == this.dataobj1.detail.detail_type) {
this.meatelist.detail_type = this.columns[i].name
}
}
}
},
//获取部门
async getDocumentList() {
const res = await userdepartment()
const deArr = res.data
let codelist = [
[], //顶级部门
[], //次级部门
[] // 负责人
]
codelist[0] = res.data.map((item) => { // 赋值
return {
id: item.id,
name: item.title
}
})
codelist[1] = res.data[0].children.map((item) => { // 赋值
return {
id: item.id,
name: item.title
}
})
let dat = await getemployee({
did: codelist[1][0].id
})
codelist[2] = dat.data.map((item) => {
return {
id: item.id,
name: item.name
}
})
this.$forceUpdate()
this.$nextTick(() => {
this.branchColumns = codelist
this.branchColumns1 = codelist
this.branchColumns2 = codelist
})
},
//监听人员加载数据
async columnCode(e) {
if (e.columnIndex == 1) {
let arr1 = []
let dat = await getemployee({
did: this.branchColumns[e.columnIndex][e.index].id
})
if (dat.data.length > 0) {
const newColumn = dat.data.map((item) => {
return {
id: item.id,
name: item.name
}
})
// 使用 Vue.set 或 this.$set 方法将新数组赋值给 columns3 数组对应位置
this.$set(this.branchColumns, 2, newColumn);
}
}
},
//监听人员加载数据
async columnCode1(e) {
if (e.columnIndex == 1) {
let arr1 = []
let dat = await getemployee({
did: this.branchColumns1[e.columnIndex][e.index].id
})
if (dat.data.length > 0) {
const newColumn = dat.data.map((item) => {
return {
id: item.id,
name: item.name
}
})
// 使用 Vue.set 或 this.$set 方法将新数组赋值给 columns3 数组对应位置
this.$set(this.branchColumns1, 2, newColumn);
}
}
},
async columnCode2(e) {
console.log(e)
if (e.columnIndex == 1) {
let arr1 = []
let dat = await getemployee({
did: this.branchColumns2[e.columnIndex][e.index].id
})
if (dat.data.length > 0) {
const newColumn = dat.data.map((item) => {
return {
id: item.id,
name: item.name
}
})
// 使用 Vue.set 或 this.$set 方法将新数组赋值给 columns3 数组对应位置
this.$set(this.branchColumns2, 2, newColumn);
}
}
},
//选择是否结束
deliveryWayChangetwo(e) {
console.log(e)
this.check = e.detail.value
},
//流程审批
async appflowcheck() {
let data = {
id: this.dataobj1.detail.id,
type: 1,
check_node: this.check,
content: this.mscontent,
check: 2,
check_admin_ids: this.check_admin_ids.toString()
}
let res = await appflow_check(data)
Toast(res.msg)
},
async appflowcheck1() {
let data = {
id: this.dataobj1.detail.id,
type: 1,
check_node: this.check,
check: 1,
content: this.mscontent,
check_admin_ids: this.check_admin_ids.toString()
}
let res = await appflow_check(data)
console.log(res)
Toast(res.msg)
},
leixin(e) {
// console.log(e)
// this.meatelist[e]==1
this.datatype = e
if (e == 'department_type') {
const detailTypeOptions = Object.entries(this.dataobj.department_type.item).map(([id, name]) => ({
id,
name
}));
this.columns = detailTypeOptions
}
if (e == 'detail_type') {
const detailTypeOptions = Object.entries(this.dataobj.detail_type.item).map(([id, name]) => ({
id,
name
}));
this.columns = detailTypeOptions
}
if (e == 'other_type') {
const detailTypeOptions = Object.entries(this.dataobj.other_type.item).map(([id, name]) => ({
id,
name
}));
this.columns = detailTypeOptions
}
// console.log(this.meatelist)
this.leavaTypeShow = true
},
leixiner() {
this.branchShow2 = true
},
branchShowclose() {
this.branchShow = false
},
branchShowclose1() {
this.branchShow1 = false
},
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, e.value[2].name)
this.check_admin_name = e.value[2].name
this.check_admin_ids.push(e.value[2].id)
this.branchShow = false
},
branchConfirm1(e) {
console.log('confirm', e, e.value[2].name)
this.copy_uids += e.value[2].id
this.copy_names += e.value[2].name + ','
this.branchShow1 = false
},
branchConfirm2(e) {
console.log('confirm', e, e.value[2].name)
this.meatelist.uid = e.value[2].id
this.meatelist.name = e.value[2].name
this.branchShow2 = false
},
/** 请假类型 */
leavaType(e) {
console.log(this.meatelist, this.datatype, e)
if (this.datatype == 'department_type') {
this.meatelist.department_type = e.name
this.leavaTypeId = e.id
} else if (this.datatype == 'detail_type') {
this.meatelist.detail_type = e.name
this.leavaTypeId1 = e.id
} else if (this.datatype == 'other_type') {
this.meatelist.other_type = e.name
this.leavaTypeId2 = e.id
}
console.log(this.leavaTypeId2)
// console.log(this.meatelist,this.datatype, e.name)
// this.meatelist.detail_type = e.name
// // this.leavaTypeVal = e.name
// this.meatelist.department_type = e.name
// this.meatelist.detail_type = e.name
// this.meatelist.other_type = e.name
this.leavaTypeShow = false
},
flowPathSelect(value) {
this.flowPath = value.name
this.flow_id = 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() {
console.log(this.leavaTypeId2)
let subData;
let subData1;
if (this.typeId == 6 || this.typeId == 7 || this.typeId == 8) {
let fileIds = [];
this.fileArray.map((item, i) => {
fileIds.push(item.id)
});
subData1 = {
detail_type: this.leavaTypeId,
content: this.meatelist.content,
check_admin_name: this.check_admin_name,
check_admin_ids: this.check_admin_ids,
flow_id: this.flow_id,
file_ids: fileIds.join(','),
copy_names: this.copy_names,
copy_uids: this.copy_uids,
type: this.typeId,
}
if (this.typeId == 8) {
subData1.start_time = this.timeData[0].timeDay + ' ' + this.timeData[0].timeHour,
subData1.end_time = this.timeData[1].timeDay + ' ' + this.timeData[1].timeHour,
subData1.department_type = this.leavaTypeId
subData1.detail_type = this.leavaTypeId1
subData1.other_type = this.leavaTypeId2
}
subData = {
...this.meatelist,
...subData1
}
} else {
let fileIds = [];
this.fileArray.map((item, i) => {
fileIds.push(item.id)
});
subData = {
detail_type: this.leavaTypeId,
start_time: this.timeData[0].timeDay + ' ' + this.timeData[0].timeHour,
end_time: this.timeData[1].timeDay + ' ' + this.timeData[1].timeHour,
duration: this.manHour,
content: this.meatelist.content,
check_admin_name: this.check_admin_name,
check_admin_ids: this.check_admin_ids,
flow_id: this.flow_id,
file_ids: fileIds.join(','),
copy_names: this.copy_names,
copy_uids: this.copy_uids,
type: this.typeId,
file: ''
}
}
console.log(subData)
try {
const res = await appapprove(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.content = ''
this.flow_id = ''
this.check_admin_name = ''
this.check_admin_ids = ''
this.copy_names = ''
this.copy_uids = ''
},
/**
* 计算两个时间戳之间相差的小时数
* */
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;
}
}
.cont_details {
padding: 24.56rpx 24.56rpx;
font-size: 28.07rpx;
background-color: #fff;
}
// 审批
.examine {
margin-bottom: 17.54rpx;
}
.record {
position: relative;
margin-bottom: 14.04rpx;
.circle {
width: 31.58rpx;
height: 31.58rpx;
background-color: #fff;
border: 2px solid #34A853;
border-radius: 50%;
margin: 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;
}
}
.text {
flex: 1;
margin-left: 7.02rpx;
}
}
.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;
}
}
:last-child {
.circle {
&::before {
display: none;
}
}
}
// 审批流程
.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>