Files
fe-manage/src/components/project/ConfirmLecturer.vue
2024-11-28 19:03:34 +08:00

648 lines
16 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>
<a-drawer
:visible="visible"
class="drawerStyle RouterFaceStus"
placement="right"
width="60%"
:zIndex="1001"
>
<div class="drawerMains">
<div class="headers">
<div class="headerTitle">{{ name }}</div>
<img
style="width: 29px; height: 29px; cursor: pointer"
src="@/assets/images/basicinfo/close.png"
@click="closeDrawer"
/>
</div>
<div class="content">
<div class="head">
<div class="list" :class="index==indexList?'active':''" @click="clickItem(item,index)" v-for="(item,index) in forData">
<div class="left">
<div>培训发生组织</div>
<div class="text">汇总金额</div>
</div>
<div class="right">
<div class="org" :title="item?.trainOrgName">{{item?.trainOrgName||'-'}}</div>
<div class="text org" :title="item?.summaryTotal">{{item?.summaryTotal||'-'}}</div>
</div>
</div>
</div>
<div class="box">
<div class="top">
<div class="item">
<a-input @pressEnter="searchData(true)" style="border-radius: 8px;width:240px;height: 40px;" v-model:value="nameUserNo" placeholder="请输入工号/讲师名称进行搜索" allowClear />
</div>
<div class="item">
<a-range-picker format="YYYY-MM-DD" valueFormat="YYYY-MM-DD" style="border-radius: 8px;width:360px;height: 40px;" v-model:value="dateValue" />
</div>
<div class="item">
<a-button type="primary" @click="searchData(true)" style="margin-right:20px;border-radius:8px;width: 100px;height: 40px;">搜索</a-button>
<a-button type="primary" @click="resetData()" style="border-radius:8px;width: 100px;height: 40px;">重置</a-button>
</div>
</div>
<div class="table">
<a-table
:columns="columns"
:data-source="searchTrue?searchList:expenseList"
:pagination="false"
:scroll="{ x: 'max-content' }"
:loading="loadingData"
>
<template #action="{ record,index }">
<div class="action">
<div @click="removeId(record,index)" class="btn" style="color: #40a9ff;cursor: pointer;">移除</div>
</div>
</template>
</a-table>
</div>
</div>
</div>
<div class="btnn">
<button class="btn1" @click="config">确认提交审批</button>
<button class="btn1" @click="qureyDrawer">确定</button>
<button class="btn2" @click="closeDrawer">取消</button>
</div>
</div>
</a-drawer>
<div>
<a-modal
:visible="modalVisible"
:footer="null"
:title="null"
:centere="true"
:closable="false"
style="margin-top: 400px"
:zIndex="1001"
@cancel="close"
>
<div class="delete">
<div class="del_header"></div>
<div class="del_main">
<div class="header">
<div class="del-icons">
<img src="@/assets/images/coursewareManage/QR.png" alt=""/>
</div>
<span>操作确认</span>
<div class="close_exit" @click="close"></div>
</div>
<div class="title">本月可提交审批次数 <span style="color:#4ea6ff"> {{ numTime }} / 10 </span></div>
<div class="body">
<div>
<span>请仔细核对讲师费信息确认无误后将自动进入(BPM系统)审批流程</span>
</div>
</div>
<div class="del_btnbox">
<div class="del_btn btn2" @click="close">
<div class="btnText">取消</div>
</div>
<div class="del_btn btn2" @click="handleConfirm">
<div class="btnText">确定</div>
</div>
</div>
</div>
</div>
</a-modal>
</div>
</template>
<script setup lang="jsx">
import {computed, defineEmits,defineProps, ref, watch} from "vue";
import {message} from "ant-design-vue";
import * as api from '@/api/Lecturer'
import dialog from "@/utils/dialog";
const props = defineProps({
visible: {
type: Boolean,
default: false,
},
name:{
type: String,
default: ""
},
ids:{
type: String,
default: ''
}
});
const loadingData = ref(false)
const modalVisible = ref(false)
const numTime = ref(0)
const close = () => {
modalVisible.value = false;
}
const handleConfirm = () => {
if(numTime.value >= 10){
message.error('提交审批次数已达上限')
return
}
numTime.value+=1
localStorage.setItem('numTime',numTime.value)
const ids = forData.value.flatMap(item => item.expenseList.map(item => item.id));
if(!ids.length){
return message.error('暂无可提交的数据')
}
api.teacherExpenseConfirm({ids:ids?.join(',')}).then(res=>{
console.log(res,'resssss')
api.submitApproval({ids:res.data?.data?.join(',')}).then(res=>{
console.log(res,'resssss')
message.success('提交成功')
close()
closeDrawer()
emit('visibleFalse',false)
}).catch(err=>{
message.destroy()
message.error(err.data.msg)
close()
closeDrawer()
emit('visibleFalse',false)
})
}).catch(err=>{
message.destroy()
message.error(err.data.msg)
close()
closeDrawer()
emit('visibleFalse',false)
})
}
const forData = ref()
const indexList = ref(0)
const expenseList = ref([])
const searchList = ref([])
const clickItem = (item,i) => {
expenseList.value = item.expenseList
indexList.value = i
resetData()
}
watch(()=>props.visible,(val)=>{
if(val){
loadingData.value = true
numTime.value = Number(localStorage.getItem('numTime')||0)
api.getListByAffiliation(
{
name: '',
ids: props.ids,
beginTime: '',
endTime: '',
}
).then(res=>{
if(res.data.code === 200){
forData.value = res.data.data
expenseList.value = res.data.data[indexList.value]?.expenseList || []
}
loadingData.value = false
resetData()
}).catch(()=>{
message.error('获取数据失败,请重新尝试')
loadingData.value = false
})
}else{
nameUserNo.value = null
dateValue.value = null
}
})
const removeId = (e,i) =>{
dialog({
content: "是否确认移除",
ok: () =>{
forData.value?.forEach(item=>{
item.expenseList?.some((i,l)=>{
if(i.id == e.id){
return item.expenseList.splice(l,1)
}
})
})
if(searchTrue.value){
searchList.value = searchList.value.filter(item=>item.id !== e.id)
expenseList.value = expenseList.value.filter(item=>item.id !== e.id)
}else{
expenseList.value = expenseList.value.filter(item=>item.id !== e.id)
}
forData.value[indexList.value].summaryTotal = forData.value[indexList.value]?.summaryTotal - e.payableExpense
}
})
}
const nameUserNo = ref(null)
const dateValue = ref(null)
const searchTrue = ref(false)
const searchData = (val) => {
searchTrue.value = val
if(!nameUserNo.value&&!dateValue.value){
searchList.value = expenseList.value;
return
}
//搜索 数组expenseList.value 参数名字或者工号nameUserNo.value 日期dateValue.value
const filteredList = expenseList.value.filter(item => {
const isNameMatch = (item.name + item.userNo).includes(nameUserNo.value);
const teachingDateTimestamp = new Date(item.teachingDate).getTime();
if(dateValue.value==null){
return isNameMatch
}
const startDateTimestamp = new Date(dateValue.value[0]).getTime();
const endDateTimestamp = new Date(dateValue.value[1]).getTime();
const isDateInRange = teachingDateTimestamp >= startDateTimestamp && teachingDateTimestamp <= endDateTimestamp;
if(nameUserNo.value&&startDateTimestamp&&endDateTimestamp){
return isNameMatch && isDateInRange;
}
return isNameMatch || isDateInRange;
});
searchList.value = filteredList;
}
const resetData = () => {
nameUserNo.value = null
dateValue.value = null
searchData(false)
}
const emit = defineEmits(['update:visible'])
const columns = [
{
title: '讲师名称',
dataIndex: 'name',
key: 'name',
align: 'center',
},
{
title: '讲师工号',
dataIndex: 'userNo',
key: 'userNo',
align: 'center',
},
{
title: '所属组织',
dataIndex: 'orgName',
key: 'orgName',
align: 'center',
ellipsis: true,
customCell :() => {return {style: {maxWidth: '200px',overflow: 'hidden',whiteSpace: 'nowrap',textOverflow:'ellipsis',cursor:'pointer'}}},
},
{
title: '讲师体系',
dataIndex: 'tsystemName',
key: 'tsystemName',
align: 'center',
},
{
title: '讲师等级',
dataIndex: 'tlevelName',
key: 'tlevelName',
align: 'center',
},
{
title: '发薪地',
dataIndex: 'payrollPlace',
key: 'payrollPlace',
align: 'center',
},
{
title: '课程类型',
dataIndex: 'courseType',
key: 'courseType',
align: 'center',
customRender: ({ text,record })=>{
switch (text) {
case 0:
return "在线课"
case 1:
return "面授课"
case 2:
return "课程开发"
case 3:
return "作业员入模培训"
case 4:
return "其他"
default:
return "-"
}
}
},
{
title: '课程名称',
dataIndex: 'courseName',
key: 'courseName',
align: 'center',
},
{
title: '授课/开发课程日期',
dataIndex: 'teachingDate',
key: 'teachingDate',
align: 'center',
},
{
title: '授课/开发课程时长',
dataIndex: 'teachingTime',
key: 'teachingTime',
align: 'center',
customRender: ({ text,record })=>{
return (text/60).toFixed(2)+'小时'
}
},
{
title: '参训人数',
dataIndex: 'studys',
key: 'studys',
align: 'center',
},
{
title: '评分',
dataIndex: 'score',
key: 'score',
align: 'center',
},
{
title: '课酬基准',
dataIndex: 'levelPay',
key: 'levelPay',
align: 'center',
},
{
title: '计划费用',
dataIndex: 'expense',
key: 'expense',
align: 'center',
},
{
title: '应发费用',
dataIndex: 'payableExpense',
key: 'payableExpense',
align: 'center',
},
{
title: '操作',
align: 'center',
fixed: 'right',
slots: { customRender: "action" },
},
]
const closeDrawer = () => emit("update:visible", false);
const qureyDrawer = () => {
const ids = forData.value.flatMap(item => item.expenseList.map(item => item.id));
if(!ids.length){
return message.error('暂无可提交的数据')
}
dialog({
content: '是否确认讲师费信息无误?提交后按“培训发生组织”汇总至审批中心,等待验证后“提交”进入审批流程。',
ok: () => {
api.teacherExpenseConfirm({ids:ids?.join(',')}).then(res=>{
console.log(res,'resssss')
message.success('提交成功')
closeDrawer()
emit('visibleFalse',false)
}).catch(err=>{
message.destroy()
message.error(err.data.msg)
closeDrawer()
emit('visibleFalse',false)
})
}
})
}
const config = () => {
if(!expenseList.value.length){
message.error('暂无可提交的数据')
return
}
modalVisible.value = true;
}
</script>
<style lang="scss" scoped>
.delete {
min-width: 424px;
background: #ffffff;
box-shadow: 0px 1px 35px 0px rgba(118, 136, 166, 0.21);
border-radius: 4px;
position: absolute;
left: 50%;
top: 10%;
transform: translate(-50%, -50%);
.del_header {
position: absolute;
width: calc(100%);
height: 40px;
background: linear-gradient(
rgba(78, 166, 255, 0.2) 0%,
rgba(78, 166, 255, 0) 100%
);
}
.del_main {
width: 100%;
position: relative;
.header {
display: flex;
align-items: center;
padding-top: 20px;
padding-left: 26px;
font-size: 16px;
.del-icons {
width: 16px;
height: 16px;
position: relative;
margin-right: 10px;
img {
width: 100%;
height: 100%;
position: absolute;
top: 0px;
left: 0px;
background-size: 100% 100%;
}
}
.close_exit {
position: absolute;
right: 42px;
cursor: pointer;
width: 20px;
height: 20px;
background-image: url(@/assets/images/coursewareManage/close.png);
background-size: 100% 100%;
}
}
.title{
padding: 0 30px;
margin-top: 34px;
}
.body {
width: 100%;
padding: 0 30px;
margin: 34px auto 56px auto;
margin-top: 10px;
display: flex;
justify-content: center;
align-items: center;
}
.del_btnbox {
display: flex;
margin: 30px auto;
justify-content: center;
.del_btn {
width: 100px;
height: 40px;
background: rgba(64, 158, 255, 0);
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
margin-right: 14px;
flex-shrink: 0;
cursor: pointer;
.btnText {
font-size: 14px;
font-weight: 400;
line-height: 40px;
}
}
.btn1 {
border: 1px solid rgba(64, 158, 255, 1);
color: #4ea6ff;
}
.btn2 {
background-color: #4ea6ff;
color: #ffffff;
}
}
}
}
.RouterFaceStus {
.drawerMains {
min-width: 600px;
margin: 0px 32px 0px 32px;
overflow-x: auto;
display: flex;
flex-direction: column;
.headers {
height: 73px;
border-bottom: 1px solid #e8e8e8;
display: flex;
justify-content: space-between;
align-items: center;
// background-color: red;
margin-bottom: 20px;
.headerTitle {
font-size: 18px;
font-weight: 600;
color: #333333;
line-height: 25px;
// margin-left: 24px;
}
}
.content{
margin: 0 20px;
.head{
display: flex;
align-items: center;
overflow-x: auto;
.list{
display: flex;
align-items: center;
background-color: #f5f5f5;
min-width: 260px;
padding: 20px 10px;
color: #ffffff;
border-radius:6px;
margin-right: 20px;
margin-bottom: 20px;
.left{
width: 35%;
min-width: 86px;
text-align:right;
margin-right:30px;
color: rgba(116, 120, 141, 0.603921568627451);
.text{
margin-top:20px;
}
}
.right{
color: #646C9A;
.org{
max-width: 148px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.text{
margin-top:20px;
}
}
}
.active{
background-color: #4ea6ff;
.left{
color: #ffffff;
}
.right{
color: #ffffff;
}
}
}
.box{
padding-bottom: 80px;
.top{
display: flex;
align-items: center;
margin-bottom: 20px;
margin-top: 10px;
.item{
margin-right: 20px;
}
}
}
}
.btnn {
height: 72px;
width: 100%;
position: absolute;
bottom: 0;
left: 0;
display: flex;
align-items: center;
justify-content: end;
box-shadow: 0px 1px 35px 0px rgba(118, 136, 166, 0.16);
background-color: #fff;
z-index: 9;
.btn2 {
width: 100px;
height: 40px;
border: 1px solid #4ea6ff;
border-radius: 8px;
color: #4ea6ff;
background-color: #fff;
cursor: pointer;
margin-right: 15px;
}
.btn1 {
cursor: pointer;
width: 100px;
height: 40px;
background: #4ea6ff;
border-radius: 8px;
border: 0;
margin-right: 15px;
color: #fff;
}
}
}
}
</style>