fourcal/src/main/resources/templates/admin/business/process-new.ftl

1239 lines
48 KiB
Plaintext
Raw Blame History

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.

<#assign base=request.contextPath />
<#import "../../common/defaultLayout.ftl" as defaultLayout>
<@defaultLayout.layout>
<link rel="stylesheet" href="${base}/element-ui/element-ui.css">
<style>
#businessPurchaseDetailsModal {
overflow: auto;
}
#businessPurchaseDetailsModal > table {
}
#procurementContractProcess {
overflow: auto;
}
.el-upload__input {
display: none !important;
}
.el-textarea .el-input__count {
line-height: 15px;
}
.admin-content-body {
margin-bottom: 100px;
}
.el-table__empty-block {
height: 60px !important;
}
.el-upload-list__item-name [class^="el-icon"] {
height: unset;
}
.el-checkbox {
margin-right: 10px;
}
.supplierChoose {
margin-bottom: 20px;
}
.el-input-number--mini .el-input-number__decrease, .el-input-number--mini .el-input-number__increase {
height: 93%;
}
.el-input-number i {
line-height: unset;
}
[v-cloak] {
display: none;
}
.supplierChoose .el-alert {
border-radius: unset;
}
.el-table .warning-row {
background: oldlace;
}
.el-table .child-row {
background: #f0f9eb;
}
</style>
<div class="admin-content" id="app">
<div class="admin-content-body">
<div class="am-cf am-padding">
<div class="am-fl am-cf"><strong class="am-text-primary am-text-lg">业务应用</strong> /
<small v-cloak>{{subTitle}}</small></div>
</div>
<div class="am-g">
<div class="am-u-sm-12 am-u-md-12" v-if="isButtonMode">
<button type="button" class="am-btn" @click="goToSaleContractProcess">
<img src="${base}/assets/process/销售合同流程@3x.png" width="36"/>
销售合同流程
</button>
<button type="button" class="am-btn" @click="newProcurementContractClick">
<img src="${base}/assets/process/业务采购流程@3x.png" width="39"/>
业务采购流程
</button>
</div>
<#-- 业务采购流程项目选择 -->
<el-dialog title="请选择项目编号" :visible.sync="procurementProjectSelectorVisible"
destroy-on-close v-cloak width="40%">
<el-autocomplete v-model="processForm.projectNo" :fetch-suggestions="queryProject" clearable
value-key="projectNo" placeholder="请输入项目编号或名称,支持模糊查询" @select="handleSelectProject"
@clear="clearProjectProcess" style="width: 100%;">
<template slot="prepend">项目编号</template>
<#--显示项目名称,但是值是 projectNo 定义显示的列表样式-->
<template slot-scope="{ item }">
<span>{{ item.name }}</span>
</template>
</el-autocomplete>
<div slot="footer">
<el-button type="primary" @click="selectProcurementDetail">下一步</el-button>
</div>
</el-dialog>
<el-dialog title="预算采购明细表" :visible="procurementDetailSelectorVisible" v-cloak width="90%" :close-on-click-modal="false">
<el-table border :data="procurementDetails">
<el-table-column type="index" :index="1" label="序号" fixed></el-table-column>
<el-table-column prop="feeType" label="费用项目" fixed width="80"></el-table-column>
<el-table-column prop="name" label="产品名称" fixed></el-table-column>
<el-table-column prop="category" label="采购类别" fixed></el-table-column>
<el-table-column prop="amount" label="数量"></el-table-column>
<el-table-column prop="unit" label="单位"></el-table-column>
<el-table-column prop="price" label="预算单价" width="100"></el-table-column>
<el-table-column prop="taxRate" label="税率(%"></el-table-column>
<el-table-column prop="totalTaxInclude_" label="含税总金额(元)" width="120"></el-table-column>
<el-table-column prop="totalTaxExclude" label="不含税金额(元)" width="120"></el-table-column>
<el-table-column prop="totalTax" label="税金(元)" width="110"></el-table-column>
<el-table-column prop="isUnderwritten" label="是否垫资"></el-table-column>
<el-table-column prop="payTime" label="支出时间" width="160"></el-table-column>
<el-table-column prop="payAmount" label="支出金额(元)" width="120"></el-table-column>
<el-table-column prop="amountAlready" label="已采购数量" width="100"></el-table-column>
<el-table-column prop="amountCurrent" label="本次采购数量" width="180">
<template slot-scope="scope">
<el-input-number :precision="2" :step="0.1" :min="0" v-model="scope.row.amountCurrent"
:disabled="scope.row.amount - scope.row.amountAlready===0" size="mini"
:max="scope.row.amount - scope.row.amountAlready" controls-position="right">
</el-input-number>
</template>
</el-table-column>
<el-table-column prop="amountLeft" label="未采购数量" width="100">
<template slot-scope="scope">
<span>{{scope.row.amount - scope.row.amountAlready}}</span>
</template>
</el-table-column>
</el-table>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="filterProcurementDetails">下一步</el-button>
</div>
</el-dialog>
<#-- 新增销售合同流程 -->
<div class="am-u-sm-12 am-u-md-12" v-cloak v-if="isSalesContractMode || isProcurementContractMode">
<el-form :inline="true" ref="contractProcessForm" :model="processForm" label-position="right" label-width="110px">
<div class="am-form-inline">
<el-tooltip :disabled="projectSelected && hasText(processForm.projectNo)" effect="light" content="项目编号或名称,支持模糊查询"
placement="top-end">
<el-form-item label="项目编号">
<el-autocomplete :disabled="projectSelected" clearable @clear="clearProjectProcess"
v-model="processForm.projectNo" :fetch-suggestions="queryProject"
value-key="projectNo" placeholder="请输入项目编号或名称" @select="handleSelectProject">
<#--显示项目名称,但是值是 projectNo 定义显示的列表样式-->
<template slot-scope="{ item }">
<el-tooltip effect="light" :content="item.name" placement="top-start">
<span>{{ item.name }}</span>
</el-tooltip>
</template>
<el-popconfirm slot="append" title="确定重新选择项目吗?填写的表单将丢弃"
:disabled="!projectSelected" @confirm="clearProjectProcess">
<el-button type="danger" slot="reference" icon="el-icon-delete" size="mini"></el-button>
</el-popconfirm>
</el-autocomplete>
</el-form-item>
</el-tooltip>
<el-tooltip :disabled="!projectSelected" effect="light" :content="processForm.projectTitle" placement="top-start">
<el-form-item label="项目标题">
<span v-if="projectSelected">{{processForm.projectTitle}}</span>
<span v-else>未选择项目</span>
</el-form-item>
</el-tooltip>
<el-form-item label="申请时间">
<span v-if="projectSelected">{{processForm.applyDate}}</span>
<span v-else>未选择项目</span>
</el-form-item>
<el-form-item :rules="[{ required: true, message: '采购模式不能为空'}]"
label="采购模式" prop="procurementMode" v-if="isProcurementContractMode">
<el-select v-model="processForm.procurementMode" placeholder="请选择采购模式">
<#list procurementMode as item>
<el-option label="${item.description}" value="${item.name()}"></el-option>
</#list>
</el-select>
</el-form-item>
<el-form-item label="项目类型" v-if="isSalesContractMode">
<span v-if="projectSelected">{{processForm.projectType}}</span>
<span v-else>未选择项目</span>
</el-form-item>
<el-form-item label="合作类型">
<span v-if="projectSelected">{{processForm.cooperationType}}</span>
<span v-else>未选择项目</span>
</el-form-item>
</div>
<div>
<el-form-item label="申请部门" prop="applyDeptId" :rules="[{ required: true, message: '申请部门不能为空'}]">
<el-cascader :options="applyDeptSectorOptions" clearable v-model="processForm.applyDeptId"
:props="{ expandTrigger: 'hover', label:'name', value: 'id'}" @change="applyDeptSelected"></el-cascader>
</el-form-item>
<el-form-item label="申请人">
<span v-if="projectSelected">{{processForm.applyPersonName}}</span>
<span v-else>未选择项目</span>
</el-form-item>
<el-form-item label="申请部门领导">
<span v-if="processForm.applyDeptLeaderName">{{processForm.applyDeptLeaderName}}</span>
<span v-else>未选择部门</span>
</el-form-item>
<el-form-item v-if="isSalesContractMode" label="申请人电话" prop="applyPersonPhone"
:rules="[{ required: true, message: '申请人电话不能为空'},
{ pattern:/^((0\d{2,3}-\d{7,8})|(1[3584]\d{9}))$/, message: '请输入合法手机号', trigger: 'blur' }]">
<el-input placeholder="请输入内容" v-model="processForm.applyPersonPhone"></el-input>
</el-form-item>
</div>
<div>
<el-form-item label="合同编号" :rules="[{ required: true, message: '合同编号不能为空'}]" prop="contractNo">
<el-input placeholder="请输入合同编号" v-model="processForm.contractNo"></el-input>
</el-form-item>
<el-form-item :rules="[{ required: true, message: '合同名称不能为空'}]"
label="合同名称" prop="contractName" v-if="isSalesContractMode">
<el-input placeholder="请输入合同名称" v-model="processForm.contractName"></el-input>
</el-form-item>
<el-form-item v-if="isProcurementContractMode" label="采购合同名称"
:rules="[{ required: true, message: '采购合同名称不能为空'}]" prop="contractName">
<el-input placeholder="请输入采购合同名称" v-model="processForm.contractName"></el-input>
</el-form-item>
<el-form-item label="合同金额">
<span v-if="projectSelected">{{processForm.contractAmount}}元</span>
<span v-else>未选择项目</span>
</el-form-item>
</div>
<div>
<el-form-item v-if="isSalesContractMode" label="客户名称" prop="clientName"
:rules="[{ required: true, message: '客户名称不能为空'}]">
<el-input placeholder="请输入客户名称" v-model="processForm.clientName"></el-input>
</el-form-item>
<el-form-item v-if="isProcurementContractMode" label="供应商名称" prop="supplierName"
:rules="[{ required: true, message: '供应商名称不能为空'}]">
<el-input placeholder="请输入供应商" v-model="processForm.supplierName"></el-input>
</el-form-item>
<el-form-item label="最终用户名称">
<#--TODO 最终用户名称-->
<span v-if="projectSelected">{{processForm.terminalCustomer}}</span>
<span v-else>未选择项目</span>
</el-form-item>
</div>
<div>
<el-form-item label="用印类型" :rules="[{ required: true, message: '用印类型不能为空'}]" prop="sealTypes">
<el-checkbox-group v-model="processForm.sealTypes">
<#list sealTypes as sealType>
<el-checkbox label="${sealType.name()}" key="key-${sealType.name()}">${sealType.description}</el-checkbox>
</#list>
</el-checkbox-group>
</el-form-item>
</div>
<div>
<el-form-item label="税率" :rules="[{ required: true, message: '税率不能为空'}]" prop="taxRate">
<el-select v-model="processForm.taxRate" placeholder="请选择税率" clearable>
<#list taxRate as rate>
<el-option label="${rate}%" value="${rate}"></el-option>
</#list>
</el-select>
</el-form-item>
<el-form-item label="是否垫资">
<span v-if="projectSelected">{{processForm.isPrepaid}}</span>
<span v-else>未选择项目</span>
</el-form-item>
<el-form-item label="垫资金额">
<span v-if="projectSelected">{{processForm.repaidAmount}}</span>
<span v-else>未选择项目</span>
</el-form-item>
<el-form-item label="预算毛利率">
<span v-if="projectSelected">{{processForm.budgetGrossMargin}}</span>
<span v-else>未选择项目</span>
</el-form-item>
</div>
<div>
<el-form-item v-if="isSalesContractMode" label="收款条件" :rules="[{ required: true, message: '收款条件不能为空'}]"
prop="paymentTerms">
<el-input type="textarea" :autosize="{ minRows: 5, maxRows: 10}" cols="90" maxlength="5000" show-word-limit
v-model="processForm.paymentTerms" placeholder="请输入收款条件限制5000字"></el-input>
</el-form-item>
<el-form-item v-if="isProcurementContractMode" label="付款条件" :rules="[{ required: true, message: '付款条件不能为空'}]"
prop="paymentTerms">
<el-input type="textarea" :autosize="{ minRows: 5, maxRows: 10}" cols="90" maxlength="5000" show-word-limit
v-model="processForm.paymentTerms" placeholder="请输入付款条件限制5000字"></el-input>
</el-form-item>
</div>
<div>
<el-form-item label="备注">
<el-input type="textarea" :autosize="{ minRows: 5, maxRows: 10}" maxlength="5000" show-word-limit
v-model="processForm.remark" placeholder="请输入备注限制5000字" cols="90"></el-input>
</el-form-item>
</div>
<div>
<el-form-item label="上传附件" :rules="[{ required: true, message: '未上传附件'}]">
<el-upload class="upload-demo"
action="${base}/file/upload"
name="files[]"
:on-remove="handleRemove"
:before-remove="beforeRemove"
:on-success="handleFileUploaded"
:limit="10"
:on-exceed="handleExceed">
<el-button size="small" type="primary">点击上传</el-button>
<div slot="tip" class="el-upload__tip">只能上传PDF、excel、word、图片、压缩包且不超过50MB</div>
</el-upload>
</el-form-item>
</div>
<div>
<el-form-item label="合同清单明细">
<el-button type="text" @click="goToContractDetail">详细清单</el-button>
</el-form-item>
</div>
</el-form>
<#-- 供应商比选材料 -->
<div class="am-u-sm-12 am-u-md-12 supplierChoose" v-if="isProcurementContractMode">
<el-alert title="供应商比选材料" type="success" center :closable="false"></el-alert>
<el-table style="width: 100%" border :data="supplierMaterialsForm" v-model="supplierMaterialsForm" empty-text="暂无">
<el-table-column type="index" :index="1" label="序号" fixed></el-table-column>
<el-table-column prop="companyName" label="公司名称" width="180" align="center">
<template slot-scope="scope">
<el-input size="mini" placeholder="请输入公司名称" v-model="scope.row.companyName"></el-input>
</template>
</el-table-column>
<el-table-column prop="totalAmount" label="合计金额" width="160" align="center">
<template slot-scope="scope">
<el-input-number size="mini" :precision="2" :step="0.1" :max="100" :min="0"
v-model="scope.row.totalAmount"></el-input-number>
</template>
</el-table-column>
<el-table-column prop="serviceTerms" label="服务条款" width="180" align="center">
<template slot-scope="scope">
<el-input size="mini" placeholder="请输入服务条款" v-model="scope.row.serviceTerms"></el-input>
</template>
</el-table-column>
<el-table-column prop="paymentTerms" label="付款条件" align="center">
<template slot-scope="scope">
<el-input size="mini" placeholder="请输入付款条件" v-model="scope.row.paymentTerms"></el-input>
</template>
</el-table-column>
<el-table-column prop="taxRate" label="税率(%" width="160" align="center">
<template slot-scope="scope">
<el-input-number size="mini" :precision="2" :step="0.1" :max="100" :min="0"
v-model="scope.row.taxRate"></el-input-number>
</template>
</el-table-column>
<el-table-column prop="remark" label="备注" align="center">
<template slot-scope="scope">
<#--
<el-input type="textarea" size="mini" maxlength="100"
v-model="scope.row.remark" placeholder="请输入备注限制100字" cols="90"></el-input>
-->
<el-input size="mini" placeholder="请输入备注"
v-model="scope.row.remark"></el-input>
</template>
</el-table-column>
<el-table-column prop="attachment" label="附件" align="center" width="150">
<template slot-scope="scope">
<el-tag size="small" v-if="scope.row.attachment">
<a :href="scope.row.attachment.uri">
<i class="el-icon-document"></i> {{scope.row.attachment.name}}
</a>
</el-tag>
<el-upload v-else class="upload-demo"
action="${base}/file/upload"
name="files[]"
:on-remove="handleRemove"
:before-remove="beforeRemove"
:on-success="handleFileUploaded"
:limit="1"
size="mini">
<el-button size="small" type="text">上传附件</el-button>
</el-upload>
</template>
</el-table-column>
</el-table>
<el-button type="primary" icon="el-icon-plus" circle size="mini" @click="addSupplierRow"
style="float: right;margin-top: 10px;"></el-button>
</div>
<el-row class="am-u-sm-12 am-u-md-12" v-cloak>
<el-button type="info" @click="goToHome">返回上一级</el-button>
<el-button type="primary" @click="saveDraft">保存草稿</el-button>
<el-button type="success" @click="submitForm">提交</el-button>
</el-row>
</div>
<#-- 销售合同清单明细 -->
<div v-cloak class="am-u-sm-12 am-u-md-12" v-if="isSaleContractDetailMode">
<el-table border :data="incomeDetails">
<el-table-column type="index" :index="1" label="序号" fixed></el-table-column>
<el-table-column prop="name" label="名称" fixed width="120"></el-table-column>
<el-table-column prop="type" label="类别"></el-table-column>
<el-table-column prop="spec" label="规格型号"></el-table-column>
<el-table-column prop="param" label="参数"></el-table-column>
<el-table-column prop="amount" label="数量"></el-table-column>
<el-table-column prop="unit" label="单位"></el-table-column>
<el-table-column prop="price" label="单价(元)" width="120"></el-table-column>
<el-table-column prop="taxRate" label="税率(%"></el-table-column>
<el-table-column prop="totalTaxInclude" label="含税金额(元)" width="120"></el-table-column>
<el-table-column prop="totalTaxExclude" label="不含税金额(元)" width="120"></el-table-column>
<el-table-column prop="totalTax" label="税金(元)" width="120"></el-table-column>
<el-table-column prop="expirationDate" label="质保期" fixed="right" width="150">
<template slot-scope="scope">
<el-input maxlength="5" size="mini" placeholder="请输入质保期" show-word-limit
v-model="scope.row.expirationDate"></el-input>
</template>
</el-table-column>
</el-table>
<el-row style="margin: 20px 0">
<el-button type="info" @click="goToSaleContractProcess">返回上一级</el-button>
<el-button type="primary" @click="submitToSaleContractProcess">保存并返回上一级</el-button>
</el-row>
</div>
<#-- 新增业务采购合同流程 -->
<#-- 选择 业务采购清单明细 -->
<div v-cloak class="am-u-sm-12 am-u-md-12" v-if="isProcurementContractDetailMode">
<el-table border :data="procurementDetails" row-key="rowKey" default-expand-all :row-class-name="procurementDetailRowClassName">
<el-table-column type="index" :index="1" label="序号" fixed></el-table-column>
<el-table-column prop="feeType" label="费用项目" width="100" fixed></el-table-column>
<el-table-column prop="name" label="产品名称" fixed></el-table-column>
<el-table-column prop="category" label="采购类别" fixed></el-table-column>
<el-table-column prop="amount" label="数量"></el-table-column>
<el-table-column prop="unit" label="单位"></el-table-column>
<el-table-column prop="price" label="预算单价" width="100"></el-table-column>
<el-table-column prop="taxRate" label="税率(%"></el-table-column>
<el-table-column prop="totalTaxInclude_" label="含税总金额(元)" width="120"></el-table-column>
<el-table-column prop="totalTaxExclude" label="不含税金额(元)" width="120"></el-table-column>
<el-table-column prop="totalTax" label="税金(元)" width="110"></el-table-column>
<el-table-column prop="isUnderwritten" label="是否垫资"></el-table-column>
<el-table-column prop="payTime" label="支出时间" width="160"></el-table-column>
<el-table-column prop="payAmount" label="支出金额(元)" width="120"></el-table-column>
<el-table-column prop="amountAlready" label="已采购数量" width="100"></el-table-column>
<el-table-column prop="amountCurrent" label="本次采购数量" width="180">
<template slot-scope="scope">
<span v-if="scope.row.newRow">{{scope.row.parent.amountCurrent}}</span>
<el-input-number v-else :precision="2" :step="0.1" :min="0" v-model="scope.row.amountCurrent"
:disabled="scope.row.amount - scope.row.amountAlready===0" size="mini"
:max="scope.row.amount - scope.row.amountAlready" controls-position="right">
</el-input-number>
</template>
</el-table-column>
<el-table-column prop="amountLeft" label="未采购数量" width="100">
<template slot-scope="scope">
<span>{{scope.row.amount - scope.row.amountAlready}}</span>
</template>
</el-table-column>
<el-table-column prop="supplierName" label="供应商名称" width="200">
<template slot-scope="scope">
<el-input size="mini" placeholder="请输入供应商名称" v-model="scope.row.supplierName"></el-input>
</template>
</el-table-column>
<el-table-column prop="manufacturerName" label="设备厂商名称" width="200">
<template slot-scope="scope">
<el-input size="mini" placeholder="请输入设备厂商名称" v-model="scope.row.manufacturerName"></el-input>
</template>
</el-table-column>
<el-table-column prop="purchaseList" label="对应采购清单" width="200">
<template slot-scope="scope">
<el-input size="mini" placeholder="请输入对应采购清单" v-model="scope.row.purchaseList"></el-input>
</template>
</el-table-column>
<el-table-column prop="spec" label="规格型号" width="200">
<template slot-scope="scope">
<el-input size="mini" placeholder="请输入规格型号" v-model="scope.row.spec"></el-input>
</template>
</el-table-column>
<el-table-column prop="procurementAmount" label="对应采购数目" width="200">
<template slot-scope="scope">
<el-input-number size="mini" :precision="2" :step="0.1" :min="0"
v-model="scope.row.procurementAmount" controls-position="right"></el-input-number>
</template>
</el-table-column>
<el-table-column prop="procurementPrice" label="采购单价" width="200">
<template slot-scope="scope">
<el-input-number size="mini" :precision="2" :step="1" :min="0"
v-model="scope.row.procurementPrice" controls-position="right"></el-input-number>
</template>
</el-table-column>
<el-table-column prop="totalTaxInclude" label="含税总金额(元)" width="200">
<template slot-scope="scope">
<el-input-number size="mini" :precision="2" :step="0.1" :min="0"
v-model="scope.row.totalTaxInclude" controls-position="right"></el-input-number>
</template>
</el-table-column>
<el-table-column width="49" fixed="right">
<template slot-scope="scope">
<el-popconfirm v-if="scope.row.newRow" title="确定删除吗?填写的表单将丢弃" @confirm="removeProcurementDetailRow(scope)">
<el-button slot="reference" type="danger" icon="el-icon-delete" circle size="mini"></el-button>
</el-popconfirm>
<el-button v-else type="primary" icon="el-icon-plus" circle size="mini"
@click="addProcurementDetailRow(scope)"></el-button>
</template>
</el-table-column>
</el-table>
<el-row style="margin: 20px 0">
<el-button type="info" @click="goToProcurementContract">返回上一级</el-button>
<el-button type="primary" @click="saveProcurementContractDetail">保存并返回上一级</el-button>
</el-row>
</div>
</div>
</div>
</div>
<script src="${base}/vue/vue.js"></script>
<script src="${base}/element-ui/element-ui.js"></script>
<script>
const procurementContractProcess = "procurementContractProcess"
const procurementContractDetail = "procurementContractDetail"
const saleContractProcess = "saleContractProcess"
const saleContractDetail = "saleContractDetail"
const BUTTON = "btn"
const saleContract = "sale_contract"
const procurementContract = "procurement_contract"
const procurementDetailProperties = [
"spec",
"amount",
"purchaseList",
"amountAlready",
"amountCurrent",
"supplierName",
"totalTaxInclude",
"manufacturerName",
"procurementPrice",
"procurementAmount"
]
const isEmpty = (obj) => {
if (!obj) {
return true
}
if (obj.hasOwnProperty('length')) {
return obj.length === 0
}
return false
}
const isNotEmpty = (obj) => {
return !isEmpty(obj)
}
const isBlank = (obj) => {
return isEmpty(obj) || (obj.trim && isEmpty(obj.trim()))
}
const hasText = (obj) => {
return !isBlank(obj)
}
const data = () => {
return {
mode: "btn", // btn , procurementContractProcess
processForm: {
sealTypes: [],
},
supplierMaterialsForm: [],
projectSelected: false,
applyDeptSectorOptions: [],
fileList: [],
// 销售合同收入明细
incomeDetails: [],
procurementDetails: [],
filteredProcurementDetails: [],
processType: "",
procurementProjectSelectorVisible: false,
procurementDetailSelectorVisible: false,
procurementDetailsRowKey: 0,
}
}
const methods = {
isEmpty,
isBlank,
hasText,
changeMode(mode) {
this.mode = mode
},
newProcurementContractClick() {
// 先选择 项目 (打开对话框)
this.processType = procurementContract
this.procurementProjectSelectorVisible = true
},
selectProcurementDetail() {
if (this.processForm.projectId) {
// 预算采购明细表 (打开对话框)
this.procurementProjectSelectorVisible = false
this.procurementDetailSelectorVisible = true
}
else {
this.$message.warning("项目还未选择")
}
},
/**
* 过滤本次流程要填写的采购清单
*/
filterProcurementDetails() {
this.procurementDetailSelectorVisible = false
this.changeMode(procurementContractProcess)
this.processType = procurementContract
const procurementDetails = this.procurementDetails.filter(detail => {
return detail.amountCurrent && detail.amountCurrent !== 0;
})
this.procurementDetails = procurementDetails
// 保留副本,提交订单的时候构建表单的时候用
this.filteredProcurementDetails = [...procurementDetails]
},
goToHome() {
// 判断是否已填写了
if (Object.keys(this.processForm).length > 2) { // 2代表 -> sealTypes,projectTitle
this.$confirm('您确认要返回上一级吗 返回后填写的表单将重置', '返回上一级', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.projectSelected = false
this.initForm({})
this.changeMode(BUTTON)
}).catch(() => {
this.$message({
type: 'info',
message: '已取消'
});
});
}
else {
this.changeMode(BUTTON)
}
},
goToSaleContractProcess() {
this.changeMode(saleContractProcess)
this.processType = saleContract
},
goToProcurementContract() {
this.changeMode(procurementContractProcess)
this.processType = procurementContract
},
/**
* 校验不通过提示
* @returns {boolean} 校验通过否
*/
checkProcurementDetails() {
const emptyRows = this.procurementDetails.filter(detail => {
return isNotEmpty(procurementDetailProperties.filter(property => isBlank(detail[property])))
})
console.log(emptyRows)
if (isNotEmpty(emptyRows)) {
const row = emptyRows[0]
this.$message.error("合同清单明细 费用项目为:'" + row.feeType + "' 采购类别为:'" + row.category + "' 的数据未填写")
return false
}
return true
},
/**
* 保存 业务采购合同清单明细,并验证表单是否填写完整,
* 如果完整就到流程表单界面
*/
saveProcurementContractDetail() {
if (this.checkProcurementDetails()) {
this.goToProcurementContract()
}
},
goToContractDetail() {
const { projectId } = this.processForm
if (projectId) {
// 选择了才能编辑详情
if (this.isSalesContractMode) {
this.changeMode(saleContractDetail)
}
else if (this.isProcurementContractMode) {
this.changeMode(procurementContractDetail)
}
}
else {
this.$message.warning("项目还未选择")
}
},
render(obj) {
console.log(obj)
},
computeProjectTitle(processForm) {
const { projectNo, projectName, applyPersonName, applyDate } = processForm
if (projectNo && projectName) {
return projectNo.trim() + "-" + projectName.trim() + "-" + applyPersonName + "-" + applyDate.split('-').join('')
}
return ""
},
initForm(form) {
this.processForm = { ...form, sealTypes: [], projectTitle: this.computeProjectTitle(form) }
},
/**
* 搜索项目
* @param q 用户输入的字符串
* @param callback 查询成功的回调
*/
queryProject(q, callback) {
if (isBlank(q)) {
callback([])
return
}
fetch("${base}/process/projects?q=" + q)
.then(res => res.json())
.then(data => {
if (data.length === 0) {
callback([])
this.$message.info('未搜索到结果');
}
else {
callback(data)
}
})
.catch(err => {
this.$message.error('项目搜索失败');
})
},
/**
* 加载选择的项目数据,填写表单需要一些初始数据
* @param selected 选择的项目信息包含IDname 字段
*/
handleSelectProject({ id, name }) {
if (!id) {
this.initForm(this.processForm)
return
}
const loading = this.$loading({
lock: true,
text: '正在加载项目',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
})
fetch("${base}/process/projects/" + id + "?processType=" + this.processType)
.then(res => res.json())
.then(data => {
const { incomeDetails, procurementDetails, ...form } = data
// 转换数据
// @formatter:off
const computeType = (type) => {
switch (type) {
case 1: return '设备'
case 2: return '工程'
case 3: return '服务'
default: return '未知'
}
}
const computeFeeType = (type) => {
switch (type) {
case 1: return '设备'
case 2: return '施工'
case 3: return '服务'
case 4: return '其他'
default: return '未知'
}
}
// @formatter:on
this.initForm(form)
this.projectSelected = true
this.incomeDetails = incomeDetails && incomeDetails.map(detail => ({
...detail, type: computeType(detail.type)
}))
let rowKey = 0
this.procurementDetails = procurementDetails && procurementDetails.map(detail => ({
...detail, feeType: computeFeeType(detail.type),
totalTaxInclude_: detail.totalTaxInclude, totalTaxInclude: undefined, // 存在相同字段转换一下
isUnderwritten: detail.isUnderwritten === 1 ? "是" : "否",
rowKey: rowKey++, children: []
}))
this.procurementDetailsRowKey = rowKey
if (!form.projectNo || !form.projectName) {
this.$message.warning("当前选择的项目没有编号或者名称");
}
})
.catch(err => {
this.$message.error("项目'" + name + "'加载失败");
})
.finally(() => loading.close())
},
clearProjectProcess() {
this.initForm({})
this.incomeDetails = []
this.projectSelected = false
this.procurementDetails = []
if (this.isProcurementContractMode) {
this.goToHome()
// 重新打开对话框选择项目
this.newProcurementContractClick()
}
},
async saveDraft() {
this.processForm.status = 'draft'
await this.submit(false)
},
async submitForm() {
this.processForm.status = 'to_be_audit'
await this.submit(true)
},
async submit(needValid) {
const processForm = this.processForm
const processType = this.processType
const fileList = this.fileList
if (!processForm.projectId) {
this.$message.error("未选择项目");
return false
}
let validStatus = !needValid
if (needValid) {
// 校验表单
this.$refs["contractProcessForm"].validate((valid) => {
if (valid) {
if (fileList.length === 0) {
this.$message.error("未上传附件");
return false
}
if (processType === saleContract) {
if (!this.checkExpirationDate()) {
return false
}
}
// 采购合同需要验证 供应商比选材料
if (processType === procurementContract) {
if (!this.checkProcurementDetails()) {
return false
}
const { procurementMode } = processForm
// specify_purchase("指定采购"),
// simple_price_comparison("简单比价"),
// price_comparison("比价"),
// competitive_evaluation("竞争性评估");
// 当“采购模式”为“指定采购”“简单比价”时,本模块为非必填模块,当为“比价”“竞争性评估”时,本模块为必填项(“备注”除外)
if (procurementMode === 'price_comparison'
|| procurementMode === 'competitive_evaluation') {
if (isEmpty(this.supplierMaterialsForm)) {
this.$message.error("供应商比选材料未填写")
return false
}
for (const item in this.supplierMaterialsForm) {
if (isEmpty(Object.keys(item))) {
this.$message.error("供应商比选材料未填写")
return false
}
for (const [key, value] of Object.entries(item)) {
if (value) {
if (typeof value === 'string') {
if (isBlank(value)) {
this.$message.error("有未填写的表单,请检查表单");
return false
}
}
}
else {
// 没有值
if (key !== 'remark') {
this.$message.error("有未填写的表单,请检查表单");
}
}
}
}
}
}
if (!processForm.applyDeptId) {
this.$message.error("申请部门还未选择");
return false
}
// 验证通过
validStatus = true
return true;
}
else {
return false
}
})
}
if (!validStatus) {
return false
}
// 提交
const loading = this.$loading({
lock: true,
text: processForm.status === 'draft' ? '正在保存草稿' : "正在提交",
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
})
const budgetCostIdMap = new Map()
this.procurementDetails.forEach(detail => {
budgetCostIdMap.set(detail.budgetCostId, detail)
})
debugger
const computePurchaseAmountDetail = budgetCostId => {
const detail = budgetCostIdMap.get(budgetCostId)
const ret = []
const map = detail => {
const ret = {}
procurementDetailProperties.forEach(property => {
ret[property] = detail[property]
})
return ret
}
ret.push(map(detail))
detail.children.forEach(detail => {
ret.push(map(detail))
})
return ret
}
const applyDeptId = processForm.applyDeptId?.join(',') // (逗号分割)
const form = {
...processForm,
processType,
applyDeptId,
attachments: fileList.map(file => ({
uri: file.response.data.url,
name: file.response.data.originName
})),
supplierMaterials: this.supplierMaterialsForm,
incomeDetails: this.incomeDetails.map(detail => ({
id: detail.id, expirationDate: detail.expirationDate
})),
purchaseAmount: this.filteredProcurementDetails.map(detail => ({
amount: detail.amount,
budgetCostId: detail.budgetCostId,
amountAlready: detail.amountAlready,
amountCurrent: detail.amountCurrent,
details: computePurchaseAmountDetail(detail.budgetCostId)
}))
}
fetch("${base}/process", {
method: 'POST', // or 'PUT'
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(form),
}).then(response => {
if (response.ok) {
this.$message({
showClose: true,
message: '提交成功',
type: 'success'
})
}
else {
return Promise.reject("失败")
}
}).catch(err => {
this.$message.error("项目提交失败");
}).finally(() => loading.close())
},
checkExpirationDate() {
const emptyRows = this.incomeDetails.filter(detail => isBlank(detail.expirationDate))
if (isNotEmpty(emptyRows)) {
const row = emptyRows[0]
this.$message.error("合同清单明细 名称为:'" + row.name + "' 类别为:'" + row.type + "' 的质保期未填写")
return false
}
return true
},
submitToSaleContractProcess() {
// 做校验
if (this.checkExpirationDate()) {
this.goToSaleContractProcess()
}
},
handleRemove(file, fileList) {
this.fileList = fileList
},
handleExceed(files, fileList) {
this.$message.warning("当前限制选择只能选择10个文件");
this.fileList = fileList
},
beforeRemove(file, fileList) {
return this.$confirm("确定移除 " + file.name + "");
},
handleFileUploaded(response, file, fileList) {
if (response.success) {
this.fileList = fileList
}
else {
this.$message.warning("上传失败");
}
},
indexMethod(index) {
return index * 1;
},
addSupplierRow() {
this.supplierMaterialsForm.push({})
},
addProcurementDetailRow(scope) {
const { row } = scope
const { children } = row
const newRow = {
...row,
rowKey: this.procurementDetailsRowKey++,
newRow: true,
parent: row // 记录上一级元素,在删除的时候使用
}
delete newRow['children']
if (children) {
row['children'].push(newRow)
}
else {
row['children'] = [newRow]
}
scope.store.table.toggleRowExpansion(row, true)
},
removeProcurementDetailRow(scope) {
const { rowKey, parent } = scope.row
parent.children = parent.children.filter(child => child.rowKey !== rowKey)
},
// 区别子项
procurementDetailRowClassName({ row, rowIndex }) {
if (row.parent) {
// 有父项说明就是子项
return 'child-row';
}
return '';
},
applyDeptSelected(value) {
if (value.length === 0) {
this.processForm['applyDept'] = null
this.processForm['applyDeptId'] = null
this.processForm['applyDeptLeaderId'] = null
this.processForm['applyDeptLeaderName'] = null
return;
}
const level1Value = value[0]
const level2Value = value.length >= 2 && value[1]
const level3Value = value.length === 3 && value[2]
const find = (options, value) => {
return options.find(option => option.id === value)
}
const leveled = []
let selected = find(this.applyDeptSectorOptions, level1Value)
leveled.push(selected)
if (selected && level2Value) {
selected = find(selected.children, level2Value)
leveled.push(selected)
if (selected && level3Value) {
selected = find(selected.children, level3Value)
if (selected) {
leveled.push(selected)
}
}
}
// applyDeptId 提交时处理
this.processForm['applyDept'] = leveled.map(level => level.name).join(',') // (逗号分割)
this.processForm['applyDeptLeaderId'] = selected.leaderId
this.processForm['applyDeptLeaderName'] = selected.leaderName
},
}
new Vue({
el: '#app',
data,
computed: {
isButtonMode() {
return this.mode === BUTTON
},
isProcurementContractMode() {
return this.mode === procurementContractProcess
},
isProcurementContractDetailMode() {
return this.mode === procurementContractDetail
},
isSalesContractMode() {
return this.mode === saleContractProcess
},
isSaleContractDetailMode() {
return this.mode === saleContractDetail
},
subTitle() {
switch (this.mode) {
case BUTTON:
return "新增流程"
case saleContractProcess:
return "新增销售合同流程"
case saleContractDetail:
return "销售合同清单明细"
case procurementContractDetail:
return "业务采购合同清单明细"
case procurementContractProcess:
return "新增业务采购合同流程"
}
}
},
methods,
mounted() {
// this.processType = procurementContract
// this.handleSelectProject({ id: 135 })
this.applyDeptSectorOptions = JSON.parse('${applyDeptSectorOptions}')
},
})
</script>
</@defaultLayout.layout>