OA/pages/leaveapplication/index2.vue

662 lines
16 KiB
Vue
Raw Permalink 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" v-for='(item,i) in dataobj' >
{{item}}
<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="i">
<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="content" 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 }}</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" @click="branchShow = true">
<view class="title">审核人:</view>
<input type="text" v-model="check_admin_name" placeholder="请选择" disabled>
</view>
<view class="cont_cell" @click="branchShow1 = true">
<view class="title">抄送人:</view>
<input type="text" v-model="copy_names" 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 :show="leavaTypeShow" keyName="name" :actions="columns" title="请选择工作类别"
@close="leavaTypeShow = false" @select="leavaType">
</u-action-sheet>
<!-- 选择审批流程 -->
<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='defaultIndex' ref="branchRef" :columns="branchColumns"
@confirm="branchConfirm" @change="branchHandler" :closeOnClickOverlay="true" @close="branchShowclose"
keyName="name">
</u-picker>
<u-picker :show="branchShow1" :defaultIndex='defaultIndex1' ref="branchRef" :columns="branchColumns1"
@confirm="branchConfirm1" @change="branchHandler" :closeOnClickOverlay="true" @close="branchShowclose1"
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 {
oaLeaveData
} from '@/static/server/server.js'
import {
oaUploads
} from '../../api/upload'
import {
Toast
} from '../../libs/uniApi'
import {
appfield,
getemployee,
userdepartment,
appapprove
} from '@/api/oa.js'
export default {
data() {
return {
defaultIndex: [0, 0, 0],
defaultIndex1: [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: [],
timeData: [{
title: '开始时间:',
timeShow: false,
timeVal: '', // 时间戳
time: '', // 完整时间
timeDay: '', // 年月日
timeHour: '', // 时分秒
},
{
title: '结束时间:',
timeShow: false,
timeVal: '', // 时间戳
time: '', // 完整时间
timeDay: '', // 年月日
timeHour: '', // 时分秒
}
],
leavaTypeShow: false,
leavaTypeVal: '',
leavaTypeId: '',
columns: [],
// 部门选择 三级级联动
branchShow: false,
branchShow1: false,
branchColumns: [],
branchColumns1: [],
isflowDate: true,
flowDate: [],
fileArray: []
}
},
onLoad(option) {
this.applist(option.type)
this.getDocumentList()
},
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 applist(type) {
let res = await appfield({
type: type
})
this.dataobj = res.data.field
const detailTypeOptions = Object.entries(res.data.field.detail_type.item).map(([id, name]) => ({
id,
name
}));
const detailTypeOptions1 = Object.entries(res.data.field.flow_id.item).map(([id, name]) => ({
id,
name
}));
this.columns = detailTypeOptions
this.flowPathSheet = detailTypeOptions1
},
//获取部门
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
})
},
//监听人员加载数据
async columnCode(e) {
if (e.columnIndex == 1) {
let arr1 = []
let dat = await getemployee({
did: this.columns3[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.columns3, 2, newColumn);
}
}
},
//监听人员加载数据
async columnCode1(e) {
if (e.columnIndex == 1) {
let arr1 = []
let dat = await getemployee({
did: this.columns3[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.columns4, 2, newColumn);
}
}
},
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 = 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
},
/** 请假类型 */
leavaType(e) {
this.leavaTypeVal = e.name
this.leavaTypeId = e.id
this.leavaTypeShow = false
},
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,
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.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: '1',
id: 0,
file: ''
}
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 = ''
},
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>