172 lines
4.9 KiB
Vue
172 lines
4.9 KiB
Vue
<template>
|
|
<el-form
|
|
ref="formRef"
|
|
:model="formData"
|
|
:rules="formRules"
|
|
v-loading="formLoading"
|
|
label-width="0px"
|
|
:inline-message="true"
|
|
:disabled="disabled"
|
|
>
|
|
<el-table :data="formData" style="width: 100%">
|
|
|
|
<el-table-column label="序号" type="index" align="center" width="60" />
|
|
<el-table-column label="项目合伙人" min-width="180">
|
|
<template #default="{ row, $index }">
|
|
<el-form-item :prop="`${$index}.partner`" :rules="formRules.partner" class="mb-0px!">
|
|
<el-select
|
|
v-model="row.partner"
|
|
filterable
|
|
clearable
|
|
placeholder="请选择"
|
|
style="width: 150px"
|
|
>
|
|
<el-option
|
|
v-for="user in userOptions"
|
|
:key="user.id"
|
|
:label="user.nickname"
|
|
:value="user.id"
|
|
/>
|
|
</el-select>
|
|
</el-form-item>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column label="比例(%)" min-width="200">
|
|
<template #default="{ row, $index }">
|
|
<el-form-item :prop="`${$index}.ratio`" :rules="formRules.ratio" class="mb-0px!">
|
|
<el-input-number
|
|
v-model="row.ratio"
|
|
:min="0"
|
|
:step="1"
|
|
:max="getMaxRatio($index)"
|
|
placeholder="请输入比例"
|
|
class="w-1/1"
|
|
/>
|
|
</el-form-item>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column label="投资额(万元)" min-width="150">
|
|
<template #default="{ row, $index }">
|
|
<el-form-item :prop="`${$index}.investment`" class="mb-0px!">
|
|
<el-input v-model="row.investment" placeholder="自动计算" :value="calcInvestment(row)" readonly />
|
|
</el-form-item>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column align="center" fixed="right" label="操作" width="60">
|
|
<template #default="{ $index }">
|
|
<el-button @click="handleDelete($index)" link>—</el-button>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
</el-form>
|
|
<el-row justify="center" class="mt-3" v-if="!disabled">
|
|
<el-button @click="handleAdd" round>+ 添加合伙人</el-button>
|
|
</el-row>
|
|
</template>
|
|
<script setup lang="ts">
|
|
import * as UserApi from '@/api/system/user'
|
|
import { ElMessage } from 'element-plus'
|
|
|
|
const props = defineProps<{
|
|
partners: any[]
|
|
disabled: boolean
|
|
price: number
|
|
}>()
|
|
const emit = defineEmits(['update:partners'])
|
|
const formLoading = ref(false)
|
|
const userOptions = ref<any[]>([])
|
|
|
|
interface PartnerRow {
|
|
partner?: string
|
|
ratio?: string | number
|
|
investment?: string | number
|
|
}
|
|
|
|
const formData = ref<PartnerRow[]>([])
|
|
|
|
const formRules = reactive({
|
|
partner: [
|
|
{ required: true, message: '项目合伙人不能为空', trigger: 'blur' },
|
|
{
|
|
validator: (_rule: any, value: string, callback: any) => {
|
|
// 检查合伙人是否重复
|
|
const count = formData.value.filter(item => item.partner === value).length
|
|
if (value && count > 1) {
|
|
callback(new Error('项目合伙人不能重复'))
|
|
} else {
|
|
callback()
|
|
}
|
|
},
|
|
trigger: 'change',
|
|
},
|
|
],
|
|
ratio: [{ required: true, message: '比例不能为空', trigger: 'blur' }],
|
|
})
|
|
const formRef = ref<any>(null)
|
|
|
|
onMounted(async () => {
|
|
// 获取用户列表
|
|
userOptions.value = await UserApi.getSimpleUserList()
|
|
})
|
|
|
|
watch(
|
|
() => props.partners,
|
|
(val) => {
|
|
formData.value = (val || []).map(item => ({
|
|
...item,
|
|
partner: item.partner ? String(item.partner) : ''
|
|
}))
|
|
},
|
|
{ immediate: true }
|
|
)
|
|
|
|
const handleAdd = () => {
|
|
formData.value.push({ partner: '', ratio: '', investment: '' })
|
|
}
|
|
|
|
const handleDelete = (index: number) => {
|
|
formData.value.splice(index, 1)
|
|
}
|
|
|
|
const validate = async () => {
|
|
const valid = await formRef.value?.validate?.()
|
|
if (!valid) return false
|
|
// 校验所有合伙人比例之和不能超过100
|
|
const totalRatio = formData.value.reduce((sum, item) => sum + (Number(item.ratio) || 0), 0)
|
|
if (totalRatio > 100) {
|
|
ElMessage.error('所有合伙人比例之和不能超过100%')
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
const calcInvestment = (row: PartnerRow) => {
|
|
const ratio = Number(row.ratio) || 0
|
|
const price = Number(props.price) || 0
|
|
return ratio && price ? ((ratio * price) / 100).toFixed(2) : ''
|
|
}
|
|
const getMaxRatio = (index: number) => {
|
|
// 计算除当前行外,其他合伙人已占用的比例
|
|
const used = formData.value.reduce((sum, item, idx) => idx !== index ? sum + (Number(item.ratio) || 0) : sum, 0)
|
|
return Math.max(0, 100 - used)
|
|
}
|
|
watch(
|
|
() => formData.value.map(item => item.ratio),
|
|
() => {
|
|
formData.value.forEach(row => {
|
|
row.investment = calcInvestment(row)
|
|
})
|
|
},
|
|
{ deep: true }
|
|
)
|
|
|
|
watch(
|
|
() => formData.value,
|
|
(val) => {
|
|
emit('update:partners', val)
|
|
},
|
|
{ deep: true }
|
|
)
|
|
|
|
defineExpose({ validate })
|
|
</script>
|