Files
mosr-web/src/views/expense-management/share-detail/add.vue
2025-06-13 14:23:37 +08:00

592 lines
20 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>
<div v-loading="loading" style="padding: 0 30px">
<el-form :model="formData" ref="form" :rules="rules" style="margin-left: 5px;margin-top: 18px">
<el-row :gutter="30">
<!-- <el-col :span="6" style="margin-left: -15px">-->
<!-- <el-form-item label="分摊名称" prop="shareName" >-->
<!-- <el-input v-model="formData.shareName" placeholder="请输入分摊名称" clearable>-->
<!-- </el-input>-->
<!-- </el-form-item>-->
<!-- </el-col>-->
<el-col :span="6" style="margin-left: -10px">
<el-form-item label="分摊月份" prop="apportionmentMonth" label-width="80">
<el-date-picker
v-model="formData.apportionmentMonth"
type="month"
format="YYYY-MM"
value-format="YYYY-MM"
placeholder="选择月"
>
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="3" >
<el-button color="#DED0B2" @click="handleAdd" style="font-size: 16px">添加一行</el-button>
</el-col>
<el-table v-if="showTable" :data="formData.tableData" style="width: 100%">
<el-table-column prop="projectId" label="项目名称" min-width="230">
<template #default="scope">
<el-form-item prop="time" :rules="scope.row.projectId?'1':rules.projectId">
<el-select v-model="scope.row.projectId" placeholder="请选择项目名称" clearable filterable @change="selectProject(scope.row,scope.$index)">
<el-option
v-for="item in nameOptions"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item>
</template>
</el-table-column>
<el-table-column prop="researchPersonnelId" label="研发人员" min-width="180">
<template #default="scope">
<el-form-item prop="researchPersonnelId">
{{ scope.row.researchPersonnel }}
<el-button color="#DED0B2" @click="showPersonnelPicker(scope.row,scope.$index)"
style="margin-left: 10px">
{{ scope.row.researchPersonnel ? '更改' : '请选择研发人员' }}
</el-button>
</el-form-item>
</template>
</el-table-column>
<el-table-column prop="wagesPayable" label="当月总工时(天)" min-width="175">
<template #default="scope">
<el-form-item prop="time" :rules="scope.row.wagesPayable?'1':rules.wagesPayable">
<div>21.75</div>
</el-form-item>
</template>
</el-table-column>
<el-table-column prop="researchDuration" label="当月研发工时(天)" min-width="175">
<template #default="scope">
<el-form-item prop="time" :rules="scope.row.researchDuration?'1':rules.researchDuration">
<el-input-number v-model="scope.row.researchDuration" placeholder="请输入当月研发工时" :controls="false"/>
</el-form-item>
</template>
</el-table-column>
<el-table-column prop="oper" label="操作" min-width="130">
<template #default="scope">
<el-button type="primary" @click="handleCopy(scope.row)" link style="font-size: 16px">复制</el-button>
<el-button type="primary" @click="handleDelete(scope.$index)" link style="font-size: 16px">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-row>
</el-form>
<user-picker :multiple="false" ref="userPicker" title="请选择研发人员" v-model:value="userList"
@ok="selectedResearchPersonnel" @cancelOrClear="researchPersonnelPickerCancel"
:setNullToSelectList="true" :isResearch="true"/>
<div class="oper-page-btn">
<el-button color="#DED0B2" v-if="routerName==='Sharedetail/add'" @click="handleSubmit(form)">提交</el-button>
<el-button color="#DED0B2" v-else @click="handleResubmit(form)">重新提交</el-button>
<el-button @click="handleBack">返回</el-button>
</div>
</div>
</template>
<script setup lang="jsx">
import {ElNotification} from "element-plus";
import {useTagsView} from '@/stores/tagsview.js'
import {
addAllocation,
getAllocationDetail,
getAllocationProcess,
getResearchUser,
getProjectOption,
editAllocation,
getAllocationDetailList, addShare
} from "@/api/expense-manage";
import {useProcessStore} from '@/stores/processStore.js';
import ProcessDiagramViewer from '@/views/workflow/common/ProcessDiagramViewer.vue';
import OperationRender from '@/views/workflow/common/OperationRender.vue'
import UserPicker from "@/views/workflow/process/common/UserPicker.vue";
localStorage.removeItem('originallySelectedList')
const userList = ref([])
const changeDiagram = ref(false)
const rules = reactive({
// shareName: [{required: true, message: '请输入分摊名称', trigger: ['blur', 'change']}],
apportionmentMonth: [{required: true, message: '请选择月份', trigger: ['blur', 'change']}],
projectId: [{required: true, message: '请选择项目名称', trigger: ['blur', 'change']}],
// researchPersonnelId: [{required: true, message: '请选择研发人员', trigger: ['blur', 'change']}],
// wagesPayable: [{required: true, message: '请输入应发工资', trigger: ['blur', 'change']}],
// performance: [{required: true, message: '请输入绩效', trigger: ['blur', 'change']}],
// reserveFund: [{required: true, message: '请输入公积金', trigger: ['blur', 'change']}],
// socialSecurity: [{required: true, message: '请输入社保', trigger: ['blur', 'change']}],
// annuity: [{required: true, message: '请输入年金', trigger: ['blur', 'change']}],
// workday: [{required: true, message: '请输入工作日', trigger: ['blur', 'change']}],
researchDuration: [{required: true, message: '请输入研发时长', trigger: ['blur', 'change']}],
})
const processStore = useProcessStore()
const opentionData = ref({})
const processInstanceData = ref()
const processDiagramViewer = ref(false)
const loading = ref(false)
const isRepeatResearchPersonnel = ref(false)
const showTable = ref(true)
const route = useRoute()
const router = useRouter()
const routerName = ref(router.currentRoute.value.name)
const tagsViewStore = useTagsView()
const formData = ref({
tableData: [
{
projectId: '',
projectName: '',
// researchPersonnelId: '',
// wagesPayable: null,
// performance: null,
// reserveFund: null,
// socialSecurity: null,
// annuity: null,
workday: '21.75',
researchDuration: null,
}
]
})
const userPicker = ref()
const form = ref()
const currentReachPerson = ref({})
const currentRow = ref()
const currentIndex = ref()
const nameOptions = ref([])
const researchOptions = ref([])
const showPersonnelPicker = (row, index) => {
currentRow.value = row
currentIndex.value = index
if (row.companyName&&row.researchPersonnelId) {
let userObj = {
id: row.researchPersonnelId,
name: row.researchPersonnel,
companyName: row.companyName,
accountType: row.accountType,
}
userList.value = [userObj]
} else if (!row.researchPersonnel) {
userList.value = []
}
nextTick(() => {
userPicker.value.showUserPicker()
})
}
const selectProject=(row,index)=>{
console.log('row,index',row,index)
//先选择人员, 再选择项目: 再添加一行,重复操作
const projectIdArray = formData.value.tableData.map(item => item.projectId)
const researchPersonnelIdArray = formData.value.tableData.map(item => item.researchPersonnelId)
console.log('projectIdArray',projectIdArray)
console.log('researchPersonnelIdArray',researchPersonnelIdArray)
const projectNumObj = getSelectProjectAndResearchPersonnelNum(projectIdArray)
const researchPersonnelNumObj = getSelectProjectAndResearchPersonnelNum(researchPersonnelIdArray)
let repeatProjectName=getProjectName(row.projectId)
// console.log('currentRow.value',currentRow.value)
// for (let researchPersonnelIdKey in researchPersonnelNumObj) {//先判断人员是否重复
// if(currentRow.value.projectId){
// if(researchPersonnelNumObj[researchPersonnelIdKey]>1){
// ElNotification({
// title: '警告',
// message: `${repeatProjectName} 项目下,同一个研发人员不能分摊多次!`,
// type: 'warning',
// })
// row.researchPersonnelId = ''
// row.researchPersonnel = ''
// row.companyName = ''
// row.accountType = ''
// }
// }
//
// }
// for (let projectIdKey in projectNumObj) {
// // console.log('projectNumObjKey', projectIdKey, projectNumObj[projectIdKey])
// if(projectNumObj[projectIdKey]>1){
// // console.log('getProjectName(projectIdKey)',getProjectName(projectIdKey))
// repeatProjectName=getProjectName(projectIdKey)
//
// }
// }
}
const researchPersonnelPickerCancel = (select) => {
console.log('select',select)
if(select.length>0){
formData.value.tableData?.forEach((item, index) => {
if (index === currentIndex.value) {
item.researchPersonnelId = select[0].id
item.researchPersonnel = select[0].name
item.companyName = select[0].companyName
item.accountType = select[0].accountType
}
})
}else{
formData.value.tableData?.forEach((item, index) => {
if (index === currentIndex.value) {
item.researchPersonnelId = ''
item.researchPersonnel = ''
item.companyName = ''
item.accountType = ''
}
})
}
}
const selectedResearchPersonnel = (select) => {
if(select.length>0){
formData.value.tableData?.forEach((item, index) => {
if (index === currentIndex.value) {
item.researchPersonnelId = select[0].id
item.researchPersonnel = select[0].name
item.companyName = select[0].companyName
item.accountType = select[0].accountType
}
})
}else{
formData.value.tableData?.forEach((item, index) => {
if (index === currentIndex.value) {
item.researchPersonnelId = ''
item.researchPersonnel = ''
item.companyName = ''
item.accountType = ''
}
})
}
//以下是为" 同一项目下,同一人不能分摊多次 "
const projectIdArray = formData.value.tableData?.map(item => item.projectId)
const researchPersonnelIdArray = formData.value.tableData?.map(item => item.researchPersonnelId)
const projectNumObj = getSelectProjectAndResearchPersonnelNum(projectIdArray)
const researchPersonnelNumObj = getSelectProjectAndResearchPersonnelNum(researchPersonnelIdArray)
let repeatProjectName=''
for (let projectIdKey in projectNumObj) {
// console.log('projectNumObjKey', projectIdKey, projectNumObj[projectIdKey])
if(projectNumObj[projectIdKey]>1){
// console.log('getProjectName(projectIdKey)',getProjectName(projectIdKey))
repeatProjectName=getProjectName(projectIdKey)
}
}
// for (let researchPersonnelIdKey in researchPersonnelNumObj) {
// // console.log('researchPersonnelIdKey', researchPersonnelIdKey, researchPersonnelNumObj[researchPersonnelIdKey])
// if(researchPersonnelNumObj[researchPersonnelIdKey]>1&&repeatProjectName&&currentRow.value.projectId){
// isRepeatResearchPersonnel.value=true
// ElNotification({
// title: '警告',
// message: `${repeatProjectName} 项目下,同一个研发人员不能分摊多次!`,
// type: 'warning',
// })
// formData.value.tableData.forEach((item,index)=>{
// if (index === currentIndex.value) {
// item.researchPersonnelId = ''
// item.researchPersonnel = ''
// item.companyName = ''
// item.accountType = ''
// }
// })
// }else{
// userList.value = select
// }
// }
}
/**
* 获取一个项目/研发人员的选择次数
* @param projectIdArray
* @returns {{}}
*/
const getSelectProjectAndResearchPersonnelNum = (projectIdArray) => {
const obj = {};
for (let i = 0, l = projectIdArray.length; i < l; i++) {
const item = projectIdArray[i];
obj[item] = (obj[item] + 1) || 1;
}
return obj;
}
const getResearchOptions = async () => {
const res = await getResearchUser()
researchOptions.value = res.data
}
const getProjectOptions = async () => {
const res = await getProjectOption()
nameOptions.value = res.data
}
const getProjectName = (id) => {
let label = ''
nameOptions.value.forEach(item => {
if (item.value == id) {
label = item.label
}
})
return label
}
const handleAdd = () => {
let row = {
projectId: '',
projectName: '',
researchPersonnelId: '',
researchPersonnel: '',
wagesPayable: null,
performance: null,
reserveFund: null,
socialSecurity: null,
annuity: null,
workday: '21.75',
researchDuration: null,
}
currentReachPerson.value.name = ''
formData.value.tableData.push(row)
}
const handleCopy = (row) => {
let copyObj = {
projectId: row.projectId,
projectName: '',
// accountType: row.accountType,
// companyName: row.companyName,
// researchPersonnelId: row.researchPersonnelId,
// researchPersonnel: row.researchPersonnel,
wagesPayable: row.wagesPayable,
performance: row.performance,
reserveFund: row.reserveFund,
socialSecurity: row.socialSecurity,
annuity: row.annuity,
workday: '21.75',
researchDuration: row.researchDuration,
}
formData.value.tableData.push(copyObj)
}
const handleDelete = (index) => {
formData.value.tableData.splice(index, 1)
}
const handleSubmit = (instance) => {
console.log('tableData', formData.value.tableData)
if (!instance) return
instance.validate(async (valid) => {
if (!valid) {
ElNotification({
title: '提示',
message: '请完善数据,再提交!',
type: 'error'
})
return;
}
let researchPersonnelId = ''
formData.value.tableData.forEach(item => {
item.projectName = getProjectName(item.projectId)
researchPersonnelId = item.researchPersonnelId
if (item.performance == 0) {
item.performance = null
}
})
if (!researchPersonnelId) {
ElNotification({
title: '提示',
message: '请选择研发人员',
type: 'error'
})
return;
}
let params = {
apportionmentMonth: formData.value.apportionmentMonth,
usrAllocations: formData.value.tableData,
}
console.log('params', params.usrAllocations, formData.value.tableData)
const resultMap = params.usrAllocations.reduce((acc, item) => {
if (!acc[item.researchPersonnelId]) {
acc[item.researchPersonnelId] = [];
}
acc[item.researchPersonnelId].push(item);
return acc;
}, {});
const exceedList = [];
Object.entries(resultMap).forEach(([id, items]) => {
const totalDuration = items.reduce((sum, item) => sum + (item.researchDuration || 0), 0);
const preciseTotalDuration = parseFloat(totalDuration.toFixed(2));
if (preciseTotalDuration > 21.75) {
// 收集超出的研发人员ID及总工时
exceedList.push({ id, totalDuration: preciseTotalDuration });
}
});
// 从 resultMap 中获取 researchPersonnel
const exceedResearchPersonnel = exceedList.map(item => {
const id = item.id;
const personnelItems = resultMap[id];
// 获取第一个对象中的 researchPersonnel假设所有对象的 researchPersonnel 相同)
const researchPersonnel = personnelItems[0].researchPersonnel;
return { id, researchPersonnel, totalDuration: item.totalDuration };
});
console.log('超过21.75的研发人员:', exceedResearchPersonnel);
if (exceedResearchPersonnel.length > 0) {
console.log('以下研发人员的总研发工时超过21.75天:', exceedResearchPersonnel);
ElNotification({
title: '提示',
message: `以下研发人员的总研发工时超过21.75天:${exceedResearchPersonnel.map(e => e.researchPersonnel).join('')}`,
type: 'warning'
});
}
// 调用函数
console.log('是大V',resultMap)
const {code, msg} = await addShare(params)
ElNotification({
title: '提示',
message: msg,
type: code === 1000 ? 'success' : 'error'
})
if (code === 1000) {
tagsViewStore.delVisitedViews(router.currentRoute.value.path)
router.push({
name: 'Share'
})
}
})
}
const handleResubmit = (instance) => {
if (!instance) return
instance.validate(async (valid) => {
if (!valid) {
ElNotification({
title: '提示',
message: '请完善数据,再提交!',
type: 'error'
})
return;
}
let researchPersonnelId = ''
formData.value.tableData.forEach(item => {
item.allocationId = formData.value.allocationId
item.projectName = getProjectName(item.projectId)
researchPersonnelId = item.researchPersonnelId
if (item.performance == 0) {
item.performance = null
}
})
if (!researchPersonnelId) {
ElNotification({
title: '提示',
message: '请选择研发人员',
type: 'error'
})
return;
}
let params = {
allocationId: formData.value.allocationId,
shareName: formData.value.shareName,
apportionmentMonth: formData.value.apportionmentMonth,
usrAllocations: formData.value.tableData,
deploymentId: processInstanceData.value.deploymentId,
}
// console.log('params', params, formData.value.tableData)
const {code, msg} = await editAllocation(params)
ElNotification({
title: '提示',
message: msg,
type: code === 1000 ? 'success' : 'error'
})
if (code === 1000) {
tagsViewStore.delVisitedViews(router.currentRoute.value.path)
router.push({
name: 'Share'
})
}
})
}
const getDetailInfo = () => {
loading.value = true
getAllocationDetail(route.query.id).then(res => {
ElNotification({
title: '提示',
message: res.msg,
type: res.code === 1000 ? 'success' : 'error'
})
if (res.code === 1000) {
getDetailList()
formData.value = res.data.formData
opentionData.value = res.data
loading.value = false
}
})
}
const getDetailList = async () => {
let params = {
allocationId: route.query.id
}
showTable.value = false
const {code, data, msg} = await getAllocationDetailList(params)
if (code === 1000) {
data.rows.forEach(item => {
item.researchPersonnelId = Number(item.researchPersonnelId)
})
formData.value.tableData = data.rows
nextTick(() => {
showTable.value = true
})
} else {
ElNotification({
title: '提示',
message: msg,
type: 'error'
})
}
}
const init = async () => {
processDiagramViewer.value = false
await getResearchOptions()
await getProjectOptions()
getAllocationProcess().then(res => {
if (res.code === 1000) {
let data = res.data
processInstanceData.value = data
processStore.setDesign(data)
processStore.runningList.value = data.runningList;
processStore.endList.value = data.endList;
processStore.noTakeList.value = data.noTakeList;
processStore.refuseList.value = data.refuseList;
processStore.passList.value = data.passList;
nextTick(() => {
processDiagramViewer.value = true
})
} else {
ElNotification({
title: '提示',
message: res.msg,
type: 'error'
})
}
})
}
const handleBack = () => {
history.back()
}
onMounted(() => {
init()
if (route.query.id) {
getDetailInfo()
}
})
</script>
<style scoped lang="scss">
:deep(.el-table--enable-row-transition) {
.el-table__body td.el-table__cell {
.cell {
.el-form-item {
margin-top: 20px;
}
}
}
}
:deep(.el-date-editor--month) {
width: 100% !important;
}
:deep(.el-input-number) {
width: 100%;
.el-input__inner {
text-align: left;
}
}
</style>