Files
fe-manage/src/components/project/BatchLecturer.vue
2025-01-13 16:25:18 +08:00

544 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>
<a-drawer
:visible="visible"
:closable="false"
class="largeDrawerInside"
placement="right"
width="80%"
>
<div class="drawerMains">
<div class="headers" style="margin-top:-24px;">
<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="box">
<div style="margin-bottom: 20px;font-size: 18px;font-weight: 700;">选择讲师费汇总:<span style="color:red;margin-left:20px;">{{expense.toFixed(2)||0}}</span></div>
<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" style="padding-bottom:72px;">
<a-table
ref="drawerContent"
:columns="columns"
:data-source="searchTrue?timesList:tableData"
:pagination="false"
:scroll="{ x: 'max-content',y:searchTrue?timesList.length?pageHeight : null:tableData.length?pageHeight : null, }"
row-key="id"
:loading="loading"
:row-selection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange }"
:custom-row="customRow"
>
<template #action="{ record }">
<div class="action">
<div style="color: #1890ff;cursor: pointer;" class="btn" v-if="selectedRowKeys.includes(record.id)" @click.stop="removeList(record)">取消选择</div>
<div style="color: #1890ff;cursor: pointer;" class="btn" v-else @click.stop="addList(record)">选择</div>
</div>
</template>
</a-table>
</div>
</div>
</div>
<div class="btnn">
<button class="btn1" @click="closeDrawer">取消</button>
<button class="btn2" @click="queryDrawer">下一步</button>
</div>
</div>
</a-drawer>
</template>
<script setup lang="jsx">
import {computed, defineEmits,defineProps, ref, watch} from "vue";
import * as api from '@/api/Lecturer'
import { message } from "ant-design-vue";
const props = defineProps({
visible: {
type: Boolean,
default: false,
},
name:{
type: String,
default: ""
}
});
const drawerContent = ref(null)
const customRow = (record) => {
return {
style:{
backgroundColor: searchTrue.value && searchList.value.some(item => item.id === record.id) ? '#a6dff9' : '',
},
onClick() {
if(selectedRowKeys.value.some(item => item === record.id)){
selectedRowKeys.value = selectedRowKeys.value.filter(item => item !== record.id)
selectsData.value = selectsData.value.filter(item => item.id !== record.id)
}else{
selectedRowKeys.value.push(record.id)
selectsData.value.push(record)
}
}
};
};
const pageHeight = computed(() => {
return window.innerHeight - 360
});
watch(()=>props.visible,(val)=>{
if(val){
loading.value = true
tableData.value = []
api.getListByStatus().then(res=>{
if(res.data.code == 200 ){
tableData.value = res.data.data
}else{
message.error(res.data.msg)
}
loading.value = false
}).catch(err=>{
loading.value = false
message.error(err.data.msg)
})
}else{
selectedRowKeys.value = []
selectsData.value = []
drawerContent.value?.$el.querySelector('.ant-table-body')?.scrollTo({top:0,behavior: 'smooth'})
resetData()
}
})
const nameUserNo = ref(null)
const dateValue = ref(null)
const searchTrue = ref(false)
const searchList = ref([])
const timesList = ref([])
const resetData = () => {
nameUserNo.value = null
dateValue.value = null
searchData(false)
}
let timeout = null
const searchData = (val) => {
// drawerContent.value.scrollTo({top:200,behavior: 'smooth'})
searchTrue.value = val
loading.value = true
if(timeout) {
clearTimeout(timeout);
}
timeout = setTimeout(() => {
loading.value = false
if(!nameUserNo.value&&!dateValue.value){
searchList.value = [];
timesList.value = tableData.value
return
}
//搜索 数组expenseList.value 参数名字或者工号nameUserNo.value 日期dateValue.value
// const filteredList = tableData.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;
// });
const timesLists = tableData.value.filter(item => {
const teachingDateTimestamp = new Date(item.teachingDate).getTime();
if(dateValue.value==null){
return tableData.value
}
const startDateTimestamp = new Date(dateValue.value[0]).getTime();
const endDateTimestamp = new Date(dateValue.value[1]).getTime();
const isDateInRange = teachingDateTimestamp >= startDateTimestamp && teachingDateTimestamp <= endDateTimestamp;
return isDateInRange;
});
selectedRowKeys.value = selectedRowKeys.value.filter(id =>
timesLists.some(item => item.id === id)
);
selectsData.value = selectsData.value.filter(item =>
timesLists.some(item2 => item2.id === item.id)
);
const filteredList = timesLists.filter(item => {
const isNameMatch = (item.name + item.userNo).includes(nameUserNo.value);
return isNameMatch
});
searchList.value = filteredList;
timesList.value = timesLists
let scrollHeight = null
filteredList.length && (scrollHeight = timesLists.findIndex(item => item.id === filteredList[0].id))
if(scrollHeight||scrollHeight==0){
drawerContent.value?.$el.querySelector('.ant-table-body')?.scrollTo({top:scrollHeight*55,behavior: 'smooth'})
}
}, 500);
}
const loading = ref(false)
const selectedRowKeys = ref([])
const selectsData = ref([]);
const onSelectChange = (e, l) => {
selectedRowKeys.value = e
selectsData.value = l
}
const emit = defineEmits(['selectedRowKeys','update:visible'])
const addList = (item) => {
selectedRowKeys.value.push(item.id)
selectsData.value.push(item)
console.log(selectedRowKeys.value)
}
const expense = ref(0)
watch(()=>selectsData.value.length,(val)=>{
if(val){
expense.value = selectsData.value.reduce((a,b)=>{
return Number(a) + Number(b.expense)
},0)
}else{
expense.value = 0
}
})
const removeList = (item) => {
selectedRowKeys.value = selectedRowKeys.value.filter(t=> t != item.id)
selectsData.value = selectsData.value.filter(t=>t.id != item.id)
}
const columns = [
{
title: '讲师名称',
dataIndex: 'name',
key: 'name',
align: 'center',
width:120,
},
{
title: '讲师工号',
dataIndex: 'userNo',
key: 'userNo',
align: 'center',
width:100
},
{
title: '课程名称',
dataIndex: 'courseName',
key: 'courseName',
align: 'left',
width:160,
customCell :() => {return {style: {maxWidth: '200px',overflow: 'hidden',whiteSpace: 'nowrap',textOverflow:'ellipsis',cursor:'pointer'}}},
},
{
title: '所属组织',
dataIndex: 'orgName',
key: 'orgName',
align: 'left',
ellipsis: true,
width:100,
customCell :() => {return {style: {maxWidth: '200px',overflow: 'hidden',whiteSpace: 'nowrap',textOverflow:'ellipsis',cursor:'pointer'}}},
},
{
title: '讲师体系',
dataIndex: 'tsystemName',
key: 'tsystemName',
align: 'left',
width:100,
customCell :() => {return {style: {maxWidth: '200px',overflow: 'hidden',whiteSpace: 'nowrap',textOverflow:'ellipsis',cursor:'pointer'}}},
},
{
title: '讲师等级',
dataIndex: 'tlevelName',
key: 'tlevelName',
align: 'center',
width:100,
customRender: ({ text })=>{
return text||'-'
}
},
{
title: '发薪地',
dataIndex: 'payrollPlace',
key: 'payrollPlace',
align: 'center',
width:120,
customCell :() => {return {style: {maxWidth: '160px',overflow: 'hidden',whiteSpace: 'nowrap',textOverflow:'ellipsis',cursor:'pointer'}}},
customRender: ({ text })=>{
return text||'-'
}
},
{
title: '课程类型',
dataIndex: 'courseType',
key: 'courseType',
align: 'center',
width:140,
customRender: ({ text,record })=>{
switch (text) {
case 0:
return "在线课"
case 1:
return "面授课"
case 2:
return "课程开发"
case 3:
return "作业员入模培训"
case 4:
return "其他"
default:
return "-"
}
}
},
{
title: '授课/开发课程日期',
dataIndex: 'teachingDate',
key: 'teachingDate',
align: 'center',
width:150
},
{
title: '授课/开发课程时长',
dataIndex: 'teachingTime',
key: 'teachingTime',
align: 'center',
width:150,
customRender: ({ text,record })=>{
return (text/60).toFixed(2)+'小时'
}
},
{
title: '参训人数',
dataIndex: 'studys',
key: 'studys',
align: 'center',
width:100,
customRender: ({ text })=>{
return text?text+'人':'0人'
}
},
{
title: '评分',
dataIndex: 'score',
key: 'score',
align: 'center',
width:100,
customRender: (value) => {
return (
<div>
{value.record.score?Number(value.record.score).toFixed(0)==0?'-':Number(value.record.score).toFixed(2)+'分' : '-'}
</div>
)
}
},
{
title: '课酬基准',
dataIndex: 'levelPay',
key: 'levelPay',
align: 'center',
width:120,
customRender: ({ text })=>{
return text||text==0?text+'元':'-'
}
},
{
title: '计划费用',
dataIndex: 'expense',
key: 'expense',
align: 'center',
width:120,
customCell :() => {return {style: {maxWidth: '160px',overflow: 'hidden',whiteSpace: 'nowrap',textOverflow:'ellipsis',cursor:'pointer'}}},
customRender: ({ text })=>{
return text?text+'元':'-'
}
},
// {
// title: '应发费用',
// dataIndex: 'payableExpense',
// key: 'payableExpense',
// align: 'center',
// },
{
title: '操作',
align: 'center',
fixed: 'right',
width: 100,
customCell:()=>{return {style:{background:'#fff'}}},
slots: { customRender: "action" },
},
]
const tableData = ref([])
const closeDrawer = () => {
emit("update:visible", false);
selectedRowKeys.value = []
selectsData.value = []
}
const queryDrawer = () => {
if(!selectedRowKeys.value.length){
message.error('请选择需要审批的数据')
return
}
emit("selectedRowKeys", selectedRowKeys.value)
// closeDrawer()
}
</script>
<style lang="scss" scoped>
.ant-table-wrapper{
border-right: 1px solid #ecf5ff;
}
/* 重置表格行的悬停效果 */
::v-deep .ant-table-tbody > tr:hover:not(.ant-table-expanded-row):not(.ant-table-row-selected) > td {
background: none;
}
// 选中鼠标划入
::v-deep .ant-table-tbody > tr.ant-table-row-selected:hover > td{
background: none ;
}
/* 未选中行的鼠标划入样式 */
::v-deep .ant-table-tbody > tr:not(.ant-table-row-selected):hover > td {
background: none;
}
/* 未选中行的鼠标划出样式 */
::v-deep .ant-table-tbody > tr:not(.ant-table-row-selected):not(:hover) > td {
background: none;
}
// 选中
::v-deep .ant-table-tbody > tr.ant-table-row-selected > td{
background: none ;
}
/* 重置表格行的选中效果 */
::v-deep .ant-table-row-selected td {
// background: none !important;
}
::v-deep .ant-table-thead > tr > th {
background-color: #eff4fc !important;
text-align: center !important;
}
.largeDrawerInside {
.drawerMains {
min-width: 600px;
// margin: 0px 32px 0px 32px;
height:100%;
overflow: auto;
display: flex;
flex-direction: column;
padding:24px;
.headers {
height: 73px;
border-bottom: 1px solid #e8e8e8;
display: flex;
justify-content: space-between;
align-items: center;
// background-color: red;
margin-bottom: 20px;
.headerTitle {
margin: 24px 0;
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: #666;
min-width: 260px;
padding: 20px 10px;
color: #ffffff;
border-radius:6px;
margin-right: 20px;
margin-bottom: 20px;
.left{
width: 35%;
text-align:right;
margin-right:30px;
.text{
margin-top:20px;
}
}
.right{
.text{
margin-top:20px;
}
}
}
.active{
background-color: #f5f5f5;
color: #000000;
}
}
.box{
.top{
display: flex;
align-items: center;
margin-bottom: 20px;
margin-top: 10px;
.item{
margin-right: 20px;
}
}
.table{
::v-deep .ant-table-cell-fix-right {
width: 120px !important;
}
}
}
}
.btnn {
height: 72px;
width: 100%;
position: absolute;
bottom: 0;
left: 0;
z-index: 9;
display: flex;
align-items: center;
justify-content: end;
box-shadow: 0px 1px 35px 0px rgba(118, 136, 166, 0.16);
background-color: #fff;
.btn1 {
width: 100px;
height: 40px;
border: 1px solid #4ea6ff;
border-radius: 8px;
color: #4ea6ff;
background-color: #fff;
cursor: pointer;
}
.btn2 {
cursor: pointer;
width: 100px;
height: 40px;
background: #4ea6ff;
border-radius: 8px;
border: 0;
margin-left: 15px;
color: #fff;
margin-right: 15px;
}
}
}
}
</style>