571 lines
18 KiB
Vue
571 lines
18 KiB
Vue
<!-- 用户编辑弹窗 -->
|
|
<template>
|
|
<ele-modal
|
|
:width="'90%'"
|
|
:visible="visible"
|
|
:confirm-loading="loading"
|
|
:maskClosable="false"
|
|
:maxable="maxable"
|
|
:title="isUpdate ? '编辑合同' : '添加合同'"
|
|
:body-style="{ paddingBottom: '8px' }"
|
|
@update:visible="updateVisible"
|
|
@ok="save"
|
|
>
|
|
<a-form
|
|
:label-col="{ md: { span: 6 }, sm: { span: 20 }, xs: { span: 24 } }"
|
|
:wrapper-col="{ md: { span: 24 }, sm: { span: 20 }, xs: { span: 24 } }"
|
|
>
|
|
<div class="title">填报人信息</div>
|
|
<a-row :gutter="16">
|
|
<a-col :md="12" :sm="24" :xs="24">
|
|
<a-form-item label="填报人">
|
|
<a-input disabled v-model:value="loginUser.username" />
|
|
</a-form-item>
|
|
</a-col>
|
|
<a-col :md="12" :sm="24" :xs="24">
|
|
<a-form-item label="填报时间">
|
|
<a-input disabled v-model:value="now" />
|
|
</a-form-item>
|
|
</a-col>
|
|
</a-row>
|
|
<div class="title">合同信息</div>
|
|
<a-row :gutter="16">
|
|
<a-col :md="8" :sm="24" :xs="24">
|
|
<a-form-item label="项目名称" v-bind="validateInfos.projectId">
|
|
<ProjectSelectModel
|
|
:placeholder="`请选择项目`"
|
|
v-model:value="projectName"
|
|
@done="chooseProject"
|
|
/>
|
|
</a-form-item>
|
|
<a-form-item label="合同编号" v-bind="validateInfos.contactNumber">
|
|
<a-input
|
|
allow-clear
|
|
:maxlength="20"
|
|
placeholder="请输入合同编号"
|
|
v-model:value="form.contactNumber"
|
|
/>
|
|
</a-form-item>
|
|
<a-form-item label="开始日期">
|
|
<a-date-picker
|
|
class="ele-fluid"
|
|
placeholder="请选择开始日期"
|
|
v-model:value="form.startDate"
|
|
valueFormat="YYYY-MM-DD"
|
|
/>
|
|
</a-form-item>
|
|
<a-form-item label="合同存档">
|
|
<a-switch :checked="form.isInStock" :checked-value="1" :un-checked-value="0" checked-children="已归档"
|
|
un-checked-children="未归档" @change="changeInStock" />
|
|
</a-form-item>
|
|
</a-col>
|
|
<a-col :md="8" :sm="24" :xs="24">
|
|
<a-form-item label="出租单位" v-bind="validateInfos.companyId">
|
|
<SelectCompany
|
|
:placeholder="`请选择出租单位`"
|
|
v-model:value="companyName"
|
|
@done="chooseCompany"
|
|
/>
|
|
</a-form-item>
|
|
<a-form-item label="承租单位" v-bind="validateInfos.customerId">
|
|
<SelectCustomer
|
|
:placeholder="`请选择承租单位`"
|
|
v-model:value="customerName"
|
|
@done="chooseCustomer"
|
|
/>
|
|
</a-form-item>
|
|
<a-form-item label="合同金额">
|
|
<a-input
|
|
allow-clear
|
|
:maxlength="20"
|
|
placeholder="请输入合同金额"
|
|
v-model:value="form.contractAmount"
|
|
>
|
|
<template #addonAfter>
|
|
<span>元</span>
|
|
</template>
|
|
</a-input>
|
|
</a-form-item>
|
|
<a-form-item label="截止日期">
|
|
<a-date-picker
|
|
class="ele-fluid"
|
|
placeholder="请选择截止日期"
|
|
v-model:value="form.endDate"
|
|
valueFormat="YYYY-MM-DD"
|
|
/>
|
|
</a-form-item>
|
|
</a-col>
|
|
<a-col :md="8" :sm="24" :xs="24">
|
|
<a-form-item label="业务负责人">
|
|
<a-input
|
|
disabled
|
|
placeholder="自动填写"
|
|
v-model:value="form.customerContact"
|
|
/>
|
|
</a-form-item>
|
|
<a-form-item label="签订日期">
|
|
<a-date-picker
|
|
class="ele-fluid"
|
|
placeholder="请选择签订日期"
|
|
v-model:value="form.signDate"
|
|
valueFormat="YYYY-MM-DD"
|
|
/>
|
|
</a-form-item>
|
|
<a-form-item label="合同约定金额">
|
|
<a-input
|
|
allow-clear
|
|
:maxlength="20"
|
|
placeholder="请输入合同约定金额"
|
|
v-model:value="form.contactAgreeAmount"
|
|
>
|
|
<template #addonAfter>
|
|
<span>元</span>
|
|
</template>
|
|
</a-input>
|
|
</a-form-item>
|
|
<a-form-item label="是否自动结算">
|
|
<a-switch :checked="form.autoSettle" :checked-value="1" :un-checked-value="0" checked-children="是"
|
|
un-checked-children="否" @change="changeAutoSettle" />
|
|
</a-form-item>
|
|
</a-col>
|
|
</a-row>
|
|
</a-form>
|
|
<div class="flex flex-col justify-start justify-start"
|
|
style="padding: 1rem 0;border-top: 1px solid #dcdfe6; border-bottom: 1px solid #dcdfe6">
|
|
<div class="flex justify-between items-center">
|
|
<span>合同电子存档</span>
|
|
<UploadFile @update:value="uploadFile" />
|
|
</div>
|
|
<div class="flex justify-start flex-wrap items-start">
|
|
<a-tag closable @close="delFile(index)" v-for="(item, index) in contractFileList" :key="index">{{ item.path }}
|
|
</a-tag>
|
|
</div>
|
|
</div>
|
|
<div class="flex justify-start items-center"
|
|
style="padding: 1rem 0;border-top: 1px solid #dcdfe6;">
|
|
<div class="flex justify-start items-center">
|
|
<unordered-list-outlined />
|
|
<span>合同签订设备清单</span>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<a-row class="bg-blue text-white text-center">
|
|
<a-col :span="3" class="p-05 border-r-white">
|
|
<span>设备名称</span>
|
|
</a-col>
|
|
<a-col :span="3" class="p-05 border-r-white">
|
|
<span>规格型号</span>
|
|
</a-col>
|
|
<a-col :span="2" class="p-05 border-r-white">
|
|
<span>签订数量</span>
|
|
</a-col>
|
|
<a-col :span="2" class="p-05 border-r-white">
|
|
<span>计划租期(月)</span>
|
|
</a-col>
|
|
<a-col :span="2" class="p-05 border-r-white">
|
|
<span>租金(元)</span>
|
|
</a-col>
|
|
<a-col :span="2" class="p-05 border-r-white">
|
|
<span>进退场费(元)</span>
|
|
</a-col>
|
|
<a-col :span="2" class="p-05 border-r-white">
|
|
<span>劳务费用(元)</span>
|
|
</a-col>
|
|
<a-col :span="2" class="p-05 border-r-white">
|
|
<span>其他费用(元)</span>
|
|
</a-col>
|
|
<a-col :span="2" class="p-05 border-r-white">
|
|
<span>预埋费(元)</span>
|
|
</a-col>
|
|
<a-col :span="2" class="p-05 border-r-white">
|
|
<span>备注</span>
|
|
</a-col>
|
|
<a-col :span="1" class="p-05">
|
|
<span>操作</span>
|
|
</a-col>
|
|
</a-row>
|
|
<div style="min-height: 10rem">
|
|
<div class=" p-05 flex justify-center items-center" v-if="contractEquipmentList.length === 0">
|
|
<span class="text-grey">暂无数据</span>
|
|
</div>
|
|
<template v-else>
|
|
<a-row class="text-center" v-for="(item, index) in contractEquipmentList"
|
|
:key="index">
|
|
<a-col :span="3" class="p-05 border-r-white">
|
|
<a-select placeholder="必选项" style="width: 100%" size="small"
|
|
v-model:value="contractEquipmentList[index].equipmentName">
|
|
<a-select-option v-for="(item, index) in equipmentList" :key="index" :value="item.name">{{ item.name
|
|
}}
|
|
</a-select-option>
|
|
</a-select>
|
|
</a-col>
|
|
<a-col :span="3" class="p-05 border-r-white">
|
|
<a-select placeholder="必选项" style="width: 100%" size="small"
|
|
v-model:value="contractEquipmentList[index].equipmentModel">
|
|
<a-select-option v-for="(item, index) in equipmentList" :key="index" :value="item.model">{{ item.model
|
|
}}
|
|
</a-select-option>
|
|
</a-select>
|
|
</a-col>
|
|
<a-col :span="2" class="p-05 border-r-white">
|
|
<a-input v-model:value="contractEquipmentList[index].num" size="small" placeholder="必填项" type="number">
|
|
<template #suffix>台</template>
|
|
</a-input>
|
|
</a-col>
|
|
<a-col :span="2" class="p-05 border-r-white">
|
|
<a-input v-model:value="contractEquipmentList[index].planRentMonth" size="small" placeholder="必填项"
|
|
type="number" />
|
|
</a-col>
|
|
<a-col :span="2" class="p-05 border-r-white">
|
|
<a-input v-model:value="contractEquipmentList[index].rentAmount" size="small" placeholder="必填项"
|
|
type="number" />
|
|
</a-col>
|
|
<a-col :span="2" class="p-05 border-r-white">
|
|
<a-input v-model:value="contractEquipmentList[index].inOutAmount" size="small" placeholder="必填项"
|
|
type="number" />
|
|
</a-col>
|
|
<a-col :span="2" class="p-05 border-r-white">
|
|
<a-input v-model:value="contractEquipmentList[index].workerAmount" size="small" placeholder="必填项"
|
|
type="number" />
|
|
</a-col>
|
|
<a-col :span="2" class="p-05 border-r-white">
|
|
<a-input v-model:value="contractEquipmentList[index].otherAmount" size="small" placeholder="必填项"
|
|
type="number" />
|
|
</a-col>
|
|
<a-col :span="2" class="p-05 border-r-white">
|
|
<a-input v-model:value="contractEquipmentList[index].preBuryAmount" size="small" placeholder="必填项"
|
|
type="number" />
|
|
</a-col>
|
|
<a-col :span="2" class="p-05 border-r-white">
|
|
<a-input v-model:value="contractEquipmentList[index].remark" size="small" placeholder="可选项" />
|
|
</a-col>
|
|
<a-col :span="1" class="p-05">
|
|
<div class="flex justify-center items-center">
|
|
<close-circle-outlined style="font-size: 1.5rem; color: pink;cursor: pointer"
|
|
@click.native="delEquipment(index)" />
|
|
</div>
|
|
</a-col>
|
|
</a-row>
|
|
</template>
|
|
</div>
|
|
<div class="my-05">
|
|
<a-button type="primary" @click.native="addEquipment">
|
|
<template #icon>
|
|
<PlusOutlined />
|
|
</template>
|
|
添加
|
|
</a-button>
|
|
</div>
|
|
</div>
|
|
</ele-modal>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { ref, reactive, watch, computed } from "vue";
|
|
import { Form, message } from "ant-design-vue";
|
|
import { assignObject } from "ele-admin-pro";
|
|
import { updateContract, addContract } from "@/api/tower/contract";
|
|
import type { Customer } from "@/api/oa/customer/model";
|
|
import { useUserStore } from "@/store/modules/user";
|
|
import { Contract } from "@/api/tower/contract/model";
|
|
import dayjs from "dayjs";
|
|
import { ContractFile } from "@/api/tower/contractFile/model";
|
|
|
|
import {
|
|
PlusOutlined,
|
|
UnorderedListOutlined,
|
|
CloseCircleOutlined
|
|
} from "@ant-design/icons-vue";
|
|
import { ContractEquipment } from "@/api/tower/contractEquipment/model";
|
|
import { TowerModel } from "@/api/tower/model/model";
|
|
import { listTowerModel } from "@/api/tower/model";
|
|
import { addBatchContractFile } from "@/api/tower/contractFile";
|
|
import { addBatchContractEquipment } from "@/api/tower/contractEquipment";
|
|
|
|
const userStore = useUserStore();
|
|
// 当前用户信息
|
|
const loginUser = computed(() => userStore.info ?? {});
|
|
|
|
const now = dayjs().format("YYYY-MM-DD HH:mm:ss");
|
|
|
|
// 是否是修改
|
|
const isUpdate = ref(false);
|
|
const useForm = Form.useForm;
|
|
const props = defineProps<{
|
|
// 弹窗是否打开
|
|
visible: boolean;
|
|
// 修改回显的数据
|
|
data?: Customer | null;
|
|
}>();
|
|
|
|
const emit = defineEmits<{
|
|
(e: "done"): void;
|
|
(e: "update:visible", visible: boolean): void;
|
|
}>();
|
|
|
|
// 提交状态
|
|
const loading = ref(false);
|
|
// 是否显示最大化切换按钮
|
|
const maxable = ref(true);
|
|
|
|
// 用户信息
|
|
const form = reactive<Contract>({
|
|
contractId: undefined,
|
|
projectId: undefined,
|
|
companyId: undefined,
|
|
customerId: undefined,
|
|
customerContact: "",
|
|
contactNumber: "",
|
|
signDate: "",
|
|
startDate: "",
|
|
endDate: "",
|
|
contractAmount: undefined,
|
|
contactAgreeAmount: undefined,
|
|
isInStock: 0,
|
|
autoSettle: 0
|
|
});
|
|
|
|
/* 更新visible */
|
|
const updateVisible = (value: boolean) => {
|
|
emit("update:visible", value);
|
|
};
|
|
|
|
// 表单验证规则
|
|
const rules = reactive({
|
|
projectId: [
|
|
{
|
|
required: true,
|
|
message: "请选择项目",
|
|
trigger: "blur"
|
|
}
|
|
],
|
|
contactNumber: [
|
|
{
|
|
required: true,
|
|
message: "请输入合同编号",
|
|
trigger: "blur"
|
|
}
|
|
],
|
|
companyId: [
|
|
{
|
|
required: true,
|
|
message: "请选择出租单位",
|
|
trigger: "blur"
|
|
}
|
|
],
|
|
customerId: [
|
|
{
|
|
required: true,
|
|
message: "请选择承租单位",
|
|
trigger: "blur"
|
|
}
|
|
]
|
|
});
|
|
|
|
const projectName = ref<string>("");
|
|
const chooseProject = (res) => {
|
|
projectName.value = res.projectName;
|
|
form.projectId = res.projectId;
|
|
};
|
|
|
|
const companyName = ref<string>("");
|
|
const chooseCompany = (res) => {
|
|
companyName.value = res.companyName;
|
|
form.companyId = res.companyId;
|
|
};
|
|
|
|
const customerName = ref<string>("");
|
|
const chooseCustomer = (res) => {
|
|
customerName.value = res.name;
|
|
form.customerId = res.customerId;
|
|
form.customerContact = res.contact;
|
|
};
|
|
|
|
const changeInStock = (checked) => {
|
|
form.isInStock = checked;
|
|
};
|
|
|
|
const changeAutoSettle = (checked) => {
|
|
form.autoSettle = checked;
|
|
};
|
|
|
|
|
|
const contractFileList = ref<ContractFile[]>([]);
|
|
const uploadFile = path => {
|
|
contractFileList.value.push({ path, contractId: 0, userId: loginUser.value.userId });
|
|
};
|
|
|
|
const delFile = index => {
|
|
contractFileList.value.splice(index, 1);
|
|
};
|
|
|
|
const getContractFileList = async () => {
|
|
|
|
};
|
|
|
|
const equipmentList = ref<TowerModel[]>([]);
|
|
const getEquipmentList = async () => {
|
|
equipmentList.value = await listTowerModel();
|
|
};
|
|
|
|
const contractEquipmentList = ref<ContractEquipment[]>([]);
|
|
const getContractEquipmentList = async () => {
|
|
|
|
};
|
|
|
|
const chooseEquipmentName = (res, index) => {
|
|
contractEquipmentList.value[index].equipmentName = res.name;
|
|
};
|
|
|
|
const delEquipment = index => {
|
|
contractEquipmentList.value.splice(index, 1);
|
|
};
|
|
|
|
const addEquipment = () => {
|
|
contractEquipmentList.value.push({
|
|
contractEquipmentId: null,
|
|
contractId: null,
|
|
equipmentName: "",
|
|
equipmentModel: "",
|
|
num: null,
|
|
planRentMonth: null,
|
|
rentAmount: null,
|
|
inOutAmount: null,
|
|
workerAmount: null,
|
|
otherAmount: null,
|
|
preBuryAmount: null,
|
|
remark: null
|
|
});
|
|
};
|
|
|
|
const { resetFields, validate, validateInfos } = useForm(form, rules);
|
|
|
|
/* 保存编辑 */
|
|
const save = () => {
|
|
validate()
|
|
.then(async () => {
|
|
loading.value = true;
|
|
// 去除空格
|
|
form.contactNumber = form.contactNumber?.replace(/\s*/g, "");
|
|
// 判断权限
|
|
// if (loginUser.value.roles?.[0].roleCode != 'admin'){
|
|
// form.status = '1';
|
|
// }
|
|
const data = {
|
|
...form
|
|
};
|
|
console.log(contractEquipmentList.value)
|
|
for (let i = 0; i < contractEquipmentList.value.length; i++) {
|
|
if (!contractEquipmentList.value[i].equipmentName) {
|
|
console.log(contractEquipmentList.value[i].equipmentName)
|
|
loading.value = false;
|
|
message.error("请选择设备");
|
|
return;
|
|
}
|
|
if (!contractEquipmentList.value[i].equipmentModel) {
|
|
loading.value = false;
|
|
message.error("请选择设备型号");
|
|
return;
|
|
}
|
|
if (!contractEquipmentList.value[i].num) {
|
|
loading.value = false;
|
|
message.error("请输入签订数量");
|
|
return;
|
|
}
|
|
if (contractEquipmentList.value[i].planRentMonth === null) {
|
|
loading.value = false;
|
|
message.error("请输入计划租期");
|
|
return;
|
|
}
|
|
if (contractEquipmentList.value[i].rentAmount === null) {
|
|
loading.value = false;
|
|
message.error("请输入租金");
|
|
return;
|
|
}
|
|
if (contractEquipmentList.value[i].inOutAmount === null) {
|
|
loading.value = false;
|
|
message.error("请输入进退场费");
|
|
return;
|
|
}
|
|
if (contractEquipmentList.value[i].workerAmount === null) {
|
|
loading.value = false;
|
|
message.error("请输入劳务费用");
|
|
return;
|
|
}
|
|
if (contractEquipmentList.value[i].otherAmount === null) {
|
|
loading.value = false;
|
|
message.error("请输入其他费用");
|
|
return;
|
|
}
|
|
if (contractEquipmentList.value[i].preBuryAmount === null) {
|
|
loading.value = false;
|
|
message.error("请输入预埋费");
|
|
return;
|
|
}
|
|
}
|
|
// 转字符串
|
|
const saveOrUpdate = isUpdate.value ? updateContract : addContract;
|
|
const res = await saveOrUpdate(data).catch((e) => {
|
|
loading.value = false;
|
|
message.error(e.message);
|
|
});
|
|
const contractId = res.data;
|
|
if (contractFileList.value.length > 0) await saveFileList(contractId);
|
|
if (contractEquipmentList.value.length > 0) await saveEquipmentList(contractId);
|
|
loading.value = false;
|
|
message.success(res.message);
|
|
updateVisible(false);
|
|
emit("done");
|
|
|
|
})
|
|
.catch(() => {
|
|
});
|
|
};
|
|
|
|
const saveFileList = async (contractId) => {
|
|
contractFileList.value.forEach((item, index) => {
|
|
contractFileList.value[index].contractId = contractId;
|
|
});
|
|
await addBatchContractFile(contractFileList.value);
|
|
};
|
|
|
|
const saveEquipmentList = async (contractId) => {
|
|
contractEquipmentList.value.forEach((item, index) => {
|
|
contractEquipmentList.value[index].contractId = contractId;
|
|
});
|
|
await addBatchContractEquipment(contractEquipmentList.value);
|
|
};
|
|
|
|
watch(
|
|
() => props.visible,
|
|
(visible) => {
|
|
if (visible) {
|
|
getEquipmentList();
|
|
if (props.data) {
|
|
loading.value = false;
|
|
assignObject(form, props.data);
|
|
isUpdate.value = true;
|
|
getContractFileList();
|
|
projectName.value = props.data.projectName;
|
|
customerName.value = props.data.customerName;
|
|
companyName.value = props.data.companyName;
|
|
} else {
|
|
isUpdate.value = false;
|
|
}
|
|
} else {
|
|
resetFields();
|
|
}
|
|
}
|
|
);
|
|
</script>
|
|
<style lang="less">
|
|
.title {
|
|
font-weight: bold;
|
|
font-size: 1.1rem;
|
|
padding-bottom: 10px;
|
|
border-bottom: 1px solid #dcdfe6;
|
|
color: #494949;
|
|
margin-bottom: 10px;
|
|
}
|
|
</style>
|