You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1006 lines
32 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div>
<!-- 付款登记-->
<xy-dialog title="付款登记" :is-show.sync="isShowPaymentRegistration" type="form" class="payment-registration"
:form="paymentRegistrationForm" :rules="paymentRegistrationRules" @submit="submit" ref="paymentRegistration">
<template v-slot:extraFormTop>
<div class="payment-registration-row">
<div class="payment-registration-row-title">受款单位</div>
<div class="payment-registration-row-content">
{{ contract.supply }}
</div>
</div>
<div class="payment-registration-row">
<div class="payment-registration-row-title">{{ nameFormat($route.path.split('_')[1]) }}名称</div>
<div class="payment-registration-row-content">
{{ contract.name }}
</div>
</div>
<div class="payment-registration-row">
<div class="payment-registration-row-title">{{ nameFormat($route.path.split('_')[1]) }}金额</div>
<div class="payment-registration-row-content">
{{ priceFormat(contract.money) }}
</div>
</div>
<div style="display: flex">
<div class="payment-registration-row">
<div class="payment-registration-row-title">已申请金额</div>
<div class="payment-registration-row-content">
{{ totalApplyMoney() }}
</div>
</div>
<div class="payment-registration-row">
<div class="payment-registration-row-title">已申请笔数</div>
<div class="payment-registration-row-content">
{{ payment.length }}
</div>
</div>
</div>
<div style="display: flex">
<div class="payment-registration-row">
<div class="payment-registration-row-title">已付金额</div>
<div class="payment-registration-row-content">
{{ totalMoney() }}
</div>
</div>
<div class="payment-registration-row">
<div class="payment-registration-row-title">支付占比</div>
<div class="payment-registration-row-content">
{{ percentPay() }}%
</div>
</div>
<div class="payment-registration-row">
<div class="payment-registration-row-title">已付笔数</div>
<div class="payment-registration-row-content">
{{ actNumsTotal() }}
</div>
<div class="payment-registration-row-content" style="color: #ff0000; padding-left: 16px; cursor: pointer">
<Poptip :transfer="true">
<div>点击查看列表</div>
<template v-slot:content>
<template v-if="payment && payment.length > 0">
<xy-table :height="200" :list="payment" :table-item="payTable">
<template v-slot:btns>
<p></p>
</template>
</xy-table>
</template>
<template v-else>
<div style="text-align: center">暂无已付笔数</div>
</template>
</template>
</Poptip>
</div>
</div>
</div>
<!-- 预算计划 -->
<div>
</div>
<!-- 是否有借款 -->
<div v-if="contract.borrows && contract.borrows.length>0">
<div style="display: flex">
<div class="payment-registration-row">
<div class="payment-registration-row-title">借款金额</div>
<div class="payment-registration-row-content">
{{ priceFormat(contract.borrows[0]['money']) }} (元)
</div>
</div>
<div class="payment-registration-row">
<div class="payment-registration-row-title">剩余还款金额</div>
<div class="payment-registration-row-content">
{{ priceFormat(contract.borrows[0]['diff']) }}(元)
</div>
</div>
</div>
</div>
<!-- 是否有 -->
</template>
<template v-slot:applyMoney>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red; font-weight: 600; padding-right: 4px">*</span>申请付款金额
</div>
<div class="xy-table-item-content xy-table-item-price">
<el-input clearable placeholder="请填写付款金额" v-model="paymentRegistrationForm.applyMoney"
style="width: 150px" />
</div>
</div>
</template>
<template v-slot:audit_money>
<div class="xy-table-item">
<div class="xy-table-item-label">审计金额</div>
<div class="xy-table-item-content xy-table-item-price">
<el-input clearable placeholder="请填写审计金额" v-model="form.audit_money" style="width: 150px" />
</div>
</div>
</template>
<template v-slot:deductionMoney>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red; font-weight: 600; padding-right: 4px">*</span>本期扣款金额
</div>
<div class="xy-table-item-content xy-table-item-price">
<el-input clearable placeholder="请填写扣款金额" v-model="paymentRegistrationForm.deductionMoney"
style="width: 150px" />
</div>
</div>
</template>
<template v-slot:remark>
<div class="xy-table-item">
<div class="xy-table-item-label">备注</div>
<div class="xy-table-item-content">
<el-input type="textarea" clearable placeholder="进度款日期2022.6.8-2022.7.7"
v-model="paymentRegistrationForm.remark" style="width: 300px" />
</div>
</div>
</template>
<template v-slot:type>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red; font-weight: 600; padding-right: 4px">*</span>款项类型
</div>
<div class="xy-table-item-content">
<el-select placeholder="选择款项类型或直接录入其他类型" v-model="paymentRegistrationForm.type" style="width: 150px"
filterable allow-create clearable popper-append-to-body>
<el-option v-for="item in paymentType" :key="item" :label="item" :value="item">
</el-option>
</el-select>
</div>
</div>
</template>
<template v-slot:isLast>
<div class="xy-table-item">
<div class="xy-table-item-label" style="width: 200px">
<span style="color: red; font-weight: 600; padding-right: 4px">*</span>是否为最后一笔
</div>
<div class="xy-table-item-content">
<el-switch active-text="是" inactive-text="否" v-model="paymentRegistrationForm.isLast" />
<!-- @change="toggleSelection"-->
</div>
</div>
</template>
<template v-slot:property>
<div class="xy-table-item">
<div class="xy-table-item-label" style="width: 200px">
<span style="color: red; font-weight: 600; padding-right: 4px">*</span>是否为资产
</div>
<div class="xy-table-item-content">
<el-switch active-text="是" inactive-text="否" v-model="paymentRegistrationForm.property" :active-value="1" :inactive-value="0" />
</div>
</div>
</template>
<template v-slot:property_type_id v-if="paymentRegistrationForm.property">
<div class="xy-table-item">
<div class="xy-table-item-label" style="width: 200px">
<span style="color: red; font-weight: 600; padding-right: 4px">*</span>资产类型
</div>
<div class="xy-table-item-content">
<el-select v-model="paymentRegistrationForm.property_type_id" style="width: 150px">
<el-option v-for="item in flowIds" :key="item.id" :value="item.id" :label="item.name"></el-option>
</el-select>
</div>
</div>
</template>
<template #files v-if="false">
<div class="xy-table-item">
<div class="xy-table-item-label">
附件
</div>
<div class="xy-table-item-content">
<el-upload style="width: 300px" ref="upload" multiple :on-success="successHandle"
:before-upload="uploadBefore" accept=".rar,.zip,.doc,.docx,.pdf,.jpg,.png,.gif,.mp4,.xls,.xlsx"
:action="action" :file-list="fileList" :auto-upload="false" :on-remove="removeHande" :limit="10">
<el-button slot="trigger" size="small" type="primary">选取文件</el-button>
<el-button style="margin-left: 10px" size="small" type="success"
@click="$refs['upload'].submit()"></el-button>
<div slot="tip" class="el-upload__tip">
支持文件格式.rar .zip .doc .docx .pdf .jpg .png .gif .mp4 .xls
.xlsx
<br />单个文件不能超过20M
</div>
</el-upload>
</div>
</div>
</template>
<template v-slot:extraFormBottom>
<div v-if="paymentRegistrationForm.plan.length===0">
<div class="select-container">
<DatePicker
:value="planSelect.year"
placeholder="选择所属年份"
placement="bottom-start"
style="width: 180px;margin-right: 10px;"
type="year"
@on-change="(e) => {
planSelect.year = e
getBudgets(true)
}"
></DatePicker>
<el-select
placeholder="科室选择"
clearable
size="small"
v-model="planSelect.plan_department_id"
style="width: 180px;margin-right: 10px;"
@change="getBudgets(true)"
>
<el-option
v-for="item in departments"
:label="item.name"
:value="item.id"
:key="item.id"
>
</el-option>
</el-select>
<el-cascader
placeholder="资金类型选择"
:options="planTypes"
:props="{
checkStrictly: false,
label: 'name',
value: 'id',
}"
:value="planSelect.type"
clearable
size="small"
style="width: 220px;margin-right: 10px;"
@change="(e) => {
planSelect.type = e[e.length - 1] || '';
getBudgets(true);
}"
/>
<Input
v-model="planSelect.name"
search
enter-button=" "
clearable
placeholder="搜索预算计划.."
@on-search="getBudgets(true)"
/>
</div>
<xy-table
:header-cell-class-name="cellClassName"
:list="plans"
:show-index="false"
:table-item="planTable"
:height="300"
style="margin-top: 10px"
ref="editorPlanTable"
border
@select="planPick"
key="planTable"
:tree-props="{ children: 'notchildren', hasChildren: 'hasChildren' }"
>
<template v-slot:btns>
<el-table-column
label="使用金额"
:fixed="$store.getters.device === 'mobile'?false:'right'"
header-align="center"
width="144"
>
<template slot-scope="scope" v-if="scope.row.pid > 0">
<InputNumber
style="width: 120px"
:min="0"
:precision="2"
:active-change="false"
v-model="scope.row._inputMoney"
:formatter="
(value) => `${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')
"
:parser="(value) => value.replace(/\$\s?|(,*)/g, '')"
></InputNumber>
</template>
</el-table-column>
</template>
</xy-table>
<div style="display: flex; justify-content: flex-end">
<Page :total="planTotal" show-elevator @on-change="pageChange" />
</div>
</div>
<div v-else>
<xy-table :list="showPlanList" key="showPlanTable" :show-index="false" :table-item="showPlanTable" :height="200" style="margin-top: 10px"
ref="editorPlanTable1">
<template v-slot:type>
<el-table-column label="分类" width="120" header-align="center">
<template slot-scope="scope">
{{findVal(planTypes,scope.row.type)}}
</template>
</el-table-column>
</template>
<template v-slot:btns>
<div></div>
</template>
</xy-table>
</div>
</template>
</xy-dialog>
</div>
</template>
<script>
import {
getparameter,getparameterTree
} from "@/api/system/dictionary";
import {
getFundLog,
addFundLog
} from "@/api/paymentRegistration/fundLog";
import { listdeptNoAuth } from '@/api/system/department'
import {
getBudget
} from "@/api/budget/budget";
import {
detailContract,
editorContract
} from "@/api/contract/contract";
import {
Message
} from "element-ui";
import {
deepCopy,
parseTime
} from "@/utils";
import {
getOatoken
} from "@/api/oatoken";
export default {
data() {
return {
flowIds: [{
flow_id: 14,
name: "供应品验收",
},
{
flow_id: 57,
name: "固定资产验收"
}
],
fileList: [],
action: process.env.VUE_APP_UPLOAD_API,
searchContent: "",
planTotal: 0,
pageIndex: 1,
//付款登记
planSelect: {
name: "",
page_size: 20,
page: 1,
// is_tree: 1,
year: new Date().getFullYear().toString(),
plan_department_id: "",
type: "",
top_pid: 1,
},
plans: [],
planTypes: [],
contract: {},
payment: [], //合同关联的付款登记
payTable: [{
label: "申请金额",
prop: "apply_money",
sortable: false,
width: 160,
align: "right",
},
{
label: "已付金额",
prop: "act_money",
sortable: false,
width: 160,
align: "right",
},
{
label: "时间",
prop: "created_at",
sortable: false,
width: 120,
formatter: (t1, t2, value) => {
return parseTime(new Date(value), "{y}-{m}-{d}");
},
},
],
paymentType: ["进度款", "结算款", "质保金"],
isShowPaymentRegistration: false,
paymentRegistrationForm: {
applyMoney: "",
//deductionMoney: "",
//audit_money: "",
type: "",
isLast: false,
property: 0,
property_type_id: "",
plan: [],
remark: "",
files: []
},
form: {
audit_money: 0,
},
paymentRegistrationRules: {
applyMoney: [{
required: true,
message: "必填",
},
{
pattern: /^\d+(\.\d+)?$/,
message: "必须为数字",
},
],
deductionMoney: [{
required: true,
message: "必填",
},
{
pattern: /^\d+(\.\d+)?$/,
message: "必须为数字",
},
],
type: [{
required: true,
message: "必选",
}, ],
},
departments:[],
planTable: [
{
sortable: false,
width: 44,
type: "selection",
reserveSelection: true,
fixed: "left",
selectable: (row, index) => {
return row.pid > 0;
},
},
{
label: "科室",
prop: "plan_department.name",
width: 120,
align: "center",
},
{
label: "年份",
prop: "year",
width: 80,
align: "center",
},
{
label: "分类",
prop: "type_detail.value",
width: 120,
},
{
label: "名称",
prop: "name",
minWidth: 180,
align: "left",
},
{
label: "内容",
prop: "content",
minWidth: 240,
align: "left",
showOverflowTooltip: true
},
{
label: "计划金额",
prop: "money",
align: "right",
width: 120,
formatter: (v1, v2, value) => {
return `${(value && parseFloat(value) !== 0) ? value : v1.update_money }`.replace(/\B(?=(\d{3})+(?!\d))/g, ",")
}
},
{
label: "实付金额",
prop: "use_money_total",
width: 120,
align: "right",
formatter: (v1, v2, value) =>
value ? `${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ",") : "",
},
{
label: "已用金额",
prop: "has_money_total",
width: 120,
align: "right",
formatter: (v1, v2, value) =>
value ? `${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ",") : "",
}],
showPlanList:[],
showPlanTable: [
{
label: "科室",
prop: "plan_department_id",
width: 120,
align: "center",
formatter: (row, column, value) => {
return this.departments.find(i => i.id === row.plan_department_id)?.name
}
},
{
label: "年份",
prop: "year",
width: 80,
align: "center",
},
{
label: "分类",
prop: "type",
width: 120,
},
{
label: "名称",
prop: "name",
minWidth: 180,
align: "left",
},
{
label: "内容",
prop: "content",
minWidth: 240,
align: "left",
showOverflowTooltip: true
},
{
label: "计划金额",
prop: "money",
align: "right",
width: 120,
formatter: (v1, v2, value) => {
return `${(value && parseFloat(value) !== 0) ? value : v1.update_money }`.replace(/\B(?=(\d{3})+(?!\d))/g, ",")
}
},
{
label: "使用金额",
prop: "use_money",
width: 120,
align: "right",
formatter: (v1, v2, value) =>
value ? `${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ",") : "",
}]
};
},
methods: {
findVal(arr, id) {
for (let i = 0; i < arr.length; i++) {
// 1. 找到匹配项直接返回name
if (arr[i].id == id) {
console.log("arr[i].name", arr[i].name);
return arr[i].name;
}
// 2. 有children数组递归查找
else if (arr[i].children instanceof Array) {
// 接收递归的返回值
const childResult = this.findVal(arr[i].children, id);
// 若子数组中找到结果,直接返回(传递到上层)
if (childResult) {
return childResult;
}
}
}
// 3. 所有层级都没找到返回null或空字符串可选
return null;
},
//上传
successHandle(response, file, fileList) {
this.fileList = fileList;
},
removeHande(file, fileList) {
this.fileList = fileList;
},
uploadBefore(file) {
console.log(file);
if ((file.size / 1000) > (20 * 1024)) {
this.$message({
type: "warning",
message: "上传图片大小超过2M",
});
return false;
}
},
// async getPlanTypes() {
// const res = await getparameter({
// number: "money_way",
// });
// this.planTypes = res.detail;
// },
async getPlanTypes() {
const res = await getparameterTree({
id: 3
});
const dataHandler = (data) => {
data.forEach(i => {
if (i.hasOwnProperty('detail')) {
i.children = i.detail.map(j => {
j.name = j.value
return j;
})
} else {
dataHandler(i['children'])
}
})
return data;
}
this.planTypes = dataHandler(res?.children) || []
},
//翻页
pageChange(e) {
this.pageIndex = e;
this.getBudgets();
},
//合计申请金额
totalApplyMoney() {
let total = 0.0;
this.payment.map((item) => {
total += Number(item.apply_money);
});
return total.toFixed(2);
},
//合计金额
totalMoney() {
let total = 0.0;
this.payment.map((item) => {
total += Number(item.act_money);
});
return total.toFixed(2);
},
//已付笔数
actNumsTotal() {
let total = 0;
this.payment.map((item) => {
if (Number(item.act_money)) {
total++;
}
});
return total;
},
//支付占比
percentPay() {
let total = this.totalMoney();
return ((total / this.contract.money) * 100 || 0).toFixed(2) || 0;
},
//获取合同信息
mergePlanData(plans, planLink) {
// 创建 plans 的映射表,键为 plan_id值为 use_money
const planMap = new Map(
plans.map(plan => [plan.plan_id, plan.use_money])
);
// 遍历 planLink为每个项添加匹配的 use_money
return planLink.map(item => {
// 如果找到匹配的 plan_id则添加 use_money否则添加 null 或默认值
const useMoney = planMap.get(item.id) || null;
return {
...item,
use_money: useMoney
};
});
},
async getContract(info) {
this.contract = await detailContract({
id: info.id,
});
this.paymentRegistrationForm.plan = this.contract.plan_link
if(this.contract.plan_link,length>0){
this.showPlanList = this.mergePlanData(this.contract.plan_link,this.contract.plans)
}
console.log("this.paymentRegistrationForm.plan",this.contract.plan_link,this.showPlanList)
if(this.contract.plan_link.legnth===0){
Message({
type: 'warning',
message: '该支出未关联预算计划,请在下方手动关联预算计划'
})
}
this.form.audit_money = this.contract.audit_money;
if (this.contract.borrows && this.contract.borrows.length > 0) {
this.paymentRegistrationForm.applyMoney =
parseFloat(this.contract.money) - parseFloat(this.contract.borrows[0].money) + parseFloat(this.contract.borrows[0].diff)
}
const res = await getFundLog({
contract_id: this.contract.id,
show_type: 1
});
this.payment = res.data;
this.fileList = res.files_detail?.map(i => {
return {
url: i?.url,
name: i?.original_name,
response: i
}
})
},
submit() {
let data = {
contract_id: this.contract.id,
apply_money: this.paymentRegistrationForm.applyMoney,
discount_money: '',
//discount_money: this.paymentRegistrationForm.deductionMoney,
type: this.paymentRegistrationForm.type,
is_end: this.paymentRegistrationForm.isLast ? 1 : 0,
remark: this.paymentRegistrationForm.remark,
audit_money: '',
//audit_money: this.paymentRegistrationForm.audit_money,
files: this.fileList ? this.fileList.map(i => i?.response?.id) : [],
property: this.paymentRegistrationForm.property,
property_type_id: this.paymentRegistrationForm.property_type_id,
};
// 如果没有关联预算计划,需要选择
if(this.paymentRegistrationForm.plan.length===0){
let contract_plan_act_links = this.$refs.editorPlanTable.getSelection()
console.log("contract_plan_act_links",contract_plan_act_links)
if(contract_plan_act_links.length<1){
Message({
type: 'warning',
message: '请选择预算计划'
})
return
}
// 判断选择的预算计划金额是否不为0
let money0 = 0
contract_plan_act_links.map(i=>{
if(parseFloat(i._inputMoney)<=0 || !i._inputMoney){
money0++
}
})
if(money0>0){
Message({
type: 'warning',
message: '选择的预算计划的使用金额不能为0'
})
return
}
data.contract_plan_links = contract_plan_act_links.map(item=>{
return {
plan_id:item.id,
new_money:this.contract.money,
use_money:item._inputMoney
}
})
}
console.log("data",data,data.contract_plan_links)
// return
addFundLog(data).then((res) => {
//付款申请后同时更新一下合同中审计金额
editorContract({
id: this.contract.id,
audit_money: this.form.audit_money,
}).then((r) => {
this.$emit("paid", {
name: this.contract?.name,
type: this.contract?.type,
number: this.contract?.number,
id: this.contract?.id,
reason: this.paymentRegistrationForm.remark,
yizhifucishu: this.actNumsTotal(),
yizhifujine: this.totalMoney(),
zongjia: this.contract?.money,
zhifucishu: this.contract?.sign_plan?.length || 0,
total: data.apply_money,
out_pay_id: res,
applyMoney: data.apply_money,
contract_id: this.contract.id,
});
this.isShowPaymentRegistration = false;
Message({
type: "success",
message: "操作成功",
});
});
this.$refs["paymentRegistration"].reset();
this.$emit('refresh')
});
},
//计划
//获取预算计划
initInputMoney(list) {
if (!Array.isArray(list)) return [];
return list.map(item => {
// 使用 Vue.set 确保响应式
this.$set(item, '_inputMoney', 0);
if (Array.isArray(item.children)) {
item.children = this.initInputMoney(item.children);
}
return item;
});
},
cellClassName({row,column,rowIndex,columnIndex}){
if(columnIndex===0){
return 'allSelect'
}
},
async getBudgets(refresh) {
let res = await getBudget(this.planSelect);
this.initInputMoney(res.list.data)
this.plans = res.list.data;
if(refresh){
this.$refs.editorPlanTable.clearSelection()
}
this.planTotal = res.list.total;
// this.toggleSelection(this.paymentRegistrationForm.plan.map(item => {
// return item.plan_id
// }))
},
getDepartment() {
listdeptNoAuth().then((res) => {
this.departments = res.data;
});
},
planPageChange(e) {
this.plansPageIndex = e;
this.getBudgets();
},
planPick (selection, row) {
if (row.year != new Date().getFullYear()) {
this.$confirm("您选择了非本年预算是否继续").catch(_ => {
this.$refs['editorPlanTable'].toggleRowSelection(row)
})
}
},
selectPlan(sel, row) {
if (sel) {
this.paymentRegistrationForm.plan = sel.map((item) => {
return {
plan_id: item.id,
use_money: item.useMoney,
new_money: item.money,
};
});
} else {
this.paymentRegistrationForm.plan = [];
}
},
toggleSelection(e) {
if (!e) {
return;
}
let plans = this.paymentRegistrationForm.plan.map((item) => {
return item.plan_id;
});
if (plans) {
this.plans
.filter((plan) => {
return plans.includes(plan.id);
})
.map((row) => {
this.$nextTick(() => {
this.$refs["planTable"].toggleRowSelection(row);
});
});
} else {
this.$refs["planTable"].clearSelection();
}
},
async getAssetsFlowIds() {
let copy = deepCopy(this.flowIds)
const res = await getparameter({
number: "asset_flow_ids"
})
try {
this.flowIds = res?.detail?.map(i => {
let data = JSON.parse(i.remark)
return {
id: i.id,
name: i.value,
...data
}
})
} catch (e) {
this.flowIds = copy
}
}
},
computed: {
priceFormat() {
return function(price) {
return Number(price)
.toFixed(2)
.replace(/(\d)(?=(\d{3})+\.)/g, "$1,");
};
},
nameFormat() {
return function(index) {
if (index == 2) {
return '报销'
}
if (index == 3) {
return '其他支出'
}
return '合同'
}
}
},
watch: {
isShowPaymentRegistration(newVal) {
if (newVal) {
this.getBudgets();
}
},
},
mounted() {
this.getPlanTypes();
},
created() {
this.getAssetsFlowIds()
this.getDepartment()
}
};
</script>
<style scoped lang="scss">
::v-deep .ivu-input-group-append.ivu-input-search{
background-color: #409EFF;
}
::v-deep .allSelect .cell {
display: none;
}
.select-container {
display: flex;
justify-content: space-between;
align-items: center;
}
.payment-registration {
&-row {
display: flex;
padding: 6px 0;
&-title {
padding: 0 10px;
}
&-content {}
}
}
.xy-table-item-label {
width: 200px;
}
.xy-table-item-price {
position: relative;
&::after {
z-index: 1;
position: absolute;
right: 0;
top: 0;
content: "";
}
::v-deep .el-input__clear {
position: relative;
right: 30px;
z-index: 2;
}
}
</style>