合同新增
							parent
							
								
									25cc74d9c3
								
							
						
					
					
						commit
						cd23457490
					
				|  | @ -4,7 +4,7 @@ NODE_ENV=development | |||
| VITE_DEV=true | ||||
| 
 | ||||
| # 请求路径 | ||||
| VITE_BASE_URL='http://172.22.3.6:48080' | ||||
| VITE_BASE_URL='http://172.22.3.168:48080' | ||||
| 
 | ||||
| # 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持 S3 服务 | ||||
| VITE_UPLOAD_TYPE=server | ||||
|  |  | |||
|  | @ -541,7 +541,7 @@ const remainingRouter: AppRouteRecordRaw[] = [ | |||
|           title: '票据模版新增', | ||||
|           noCache: true, | ||||
|           hidden: true, | ||||
|           activeMenu: '/crm/business' | ||||
|           activeMenu: '/crm/bill-template' | ||||
|         }, | ||||
|         component: () => import('@/views/crm/billtemplate/BillTemplateForm.vue') | ||||
|       }, | ||||
|  | @ -552,7 +552,7 @@ const remainingRouter: AppRouteRecordRaw[] = [ | |||
|           title: '票据模版编辑', | ||||
|           noCache: true, | ||||
|           hidden: true, | ||||
|           activeMenu: '/crm/business' | ||||
|           activeMenu: '/crm/bill-template' | ||||
|         }, | ||||
|         component: () => import('@/views/crm/billtemplate/BillTemplateForm.vue') | ||||
|       }, | ||||
|  | @ -563,7 +563,7 @@ const remainingRouter: AppRouteRecordRaw[] = [ | |||
|           title: '方案报价新增', | ||||
|           noCache: true, | ||||
|           hidden: true, | ||||
|           activeMenu: '/crm/business' | ||||
|           activeMenu: '/crm/quotation' | ||||
|         }, | ||||
|         component: () => import('@/views/crm/quotation/QuotationForm.vue') | ||||
|       }, | ||||
|  | @ -574,7 +574,7 @@ const remainingRouter: AppRouteRecordRaw[] = [ | |||
|           title: '方案报价编辑', | ||||
|           noCache: true, | ||||
|           hidden: true, | ||||
|           activeMenu: '/crm/business' | ||||
|           activeMenu: '/crm/quotation' | ||||
|         }, | ||||
|         component: () => import('@/views/crm/quotation/QuotationForm.vue') | ||||
|       }, | ||||
|  | @ -585,7 +585,7 @@ const remainingRouter: AppRouteRecordRaw[] = [ | |||
|           title: '方案报价详情', | ||||
|           noCache: true, | ||||
|           hidden: true, | ||||
|           activeMenu: '/crm/business' | ||||
|           activeMenu: '/crm/quotation' | ||||
|         }, | ||||
|         component: () => import('@/views/crm/quotation/QuotationDetail.vue') | ||||
|       }, | ||||
|  | @ -611,6 +611,39 @@ const remainingRouter: AppRouteRecordRaw[] = [ | |||
|         }, | ||||
|         component: () => import('@/views/crm/business/BusinessForm.vue') | ||||
|       }, | ||||
|       { | ||||
|         path: 'contract/add', | ||||
|         name: 'CrmContractAdd', | ||||
|         meta: { | ||||
|           title: '合同新增', | ||||
|           noCache: true, | ||||
|           hidden: true, | ||||
|           activeMenu: '/crm/contract' | ||||
|         }, | ||||
|         component: () => import('@/views/crm/contract/ContractForm.vue') | ||||
|       }, | ||||
|       { | ||||
|         path: 'contract/edit', | ||||
|         name: 'CrmContractEdit', | ||||
|         meta: { | ||||
|           title: '合同编辑', | ||||
|           noCache: true, | ||||
|           hidden: true, | ||||
|           activeMenu: '/crm/contract' | ||||
|         }, | ||||
|         component: () => import('@/views/crm/contract/ContractForm.vue') | ||||
|       }, | ||||
|       { | ||||
|         path: 'contract/change', | ||||
|         name: 'CrmContractChange', | ||||
|         meta: { | ||||
|           title: '合同变更', | ||||
|           noCache: true, | ||||
|           hidden: true, | ||||
|           activeMenu: '/crm/contract' | ||||
|         }, | ||||
|         component: () => import('@/views/crm/contract/ContractChange.vue') | ||||
|       }, | ||||
|       { | ||||
|         path: 'contract/detail/:id', | ||||
|         name: 'CrmContractDetail', | ||||
|  |  | |||
|  | @ -0,0 +1,658 @@ | |||
| <template> | ||||
|   <ContentWrap class="mt-10px"> | ||||
|     <el-form | ||||
|       ref="formRef" | ||||
|       v-loading="formLoading" | ||||
|       :model="formData" | ||||
|       :rules="formRules" | ||||
|       label-width="120px" | ||||
|     > | ||||
|       <el-row> | ||||
|         <el-col :span="8"> | ||||
|           <el-form-item label="合同查询" prop="quotationId"> | ||||
|             <el-select | ||||
|               @change="handleQuotationChange" | ||||
|               v-model="formData.quotationId" | ||||
|               class="w-1/1" | ||||
|             > | ||||
|               <el-option | ||||
|                 v-for="item in quotationList" | ||||
|                 :key="item.id" | ||||
|                 :label="item.no" | ||||
|                 :value="item.id" | ||||
|               /> | ||||
|             </el-select> | ||||
|           </el-form-item> | ||||
|         </el-col> | ||||
|         <el-col :span="8"> | ||||
|           <el-form-item label="合同名称" prop="name"> | ||||
|             <el-input v-model="formData.name" placeholder="请输入合同名称" /> | ||||
|           </el-form-item> | ||||
|         </el-col> | ||||
|       </el-row> | ||||
| 
 | ||||
|       <el-row> | ||||
|         <el-col :span="8"> | ||||
|           <el-form-item label="报价单编号" prop="quotationId"> | ||||
|             <el-select | ||||
|               @change="handleQuotationChange" | ||||
|               v-model="formData.quotationId" | ||||
|               class="w-1/1" | ||||
|             > | ||||
|               <el-option | ||||
|                 v-for="item in quotationList" | ||||
|                 :key="item.id" | ||||
|                 :label="item.no" | ||||
|                 :value="item.id" | ||||
|               /> | ||||
|             </el-select> | ||||
|           </el-form-item> | ||||
|         </el-col> | ||||
|         <el-col :span="8"> | ||||
|           <el-form-item label="客户名称" prop="customerId"> | ||||
|             <el-select | ||||
|               v-model="formData.customerId" | ||||
|               disabled="" | ||||
|               placeholder="请选择客户" | ||||
|               class="w-1/1" | ||||
|             > | ||||
|               <el-option | ||||
|                 v-for="item in contactList" | ||||
|                 :key="item.id" | ||||
|                 :label="item.name" | ||||
|                 :value="item.id" | ||||
|               /> | ||||
|             </el-select> | ||||
|           </el-form-item> | ||||
|         </el-col> | ||||
|       </el-row> | ||||
| 
 | ||||
|       <el-row> | ||||
|          | ||||
|         <el-col :span="8"> | ||||
|           <el-form-item label="合同签订日期" prop="startTime"> | ||||
|             <el-date-picker | ||||
|               v-model="formData.startTime" | ||||
|               type="date" | ||||
|               value-format="x" | ||||
|               placeholder="选择合同签订日期" | ||||
|             /> | ||||
|           </el-form-item> | ||||
|         </el-col> | ||||
|         <el-col :span="8"> | ||||
|           <el-form-item label="合同结束时间" prop="endTime"> | ||||
|             <el-date-picker | ||||
|               v-model="formData.endTime" | ||||
|               type="date" | ||||
|               value-format="x" | ||||
|               placeholder="选择合同结束时间" | ||||
|             /> | ||||
|           </el-form-item> | ||||
|         </el-col> | ||||
|       </el-row> | ||||
| 
 | ||||
|       <el-row> | ||||
|         <el-col :span="8"> | ||||
|           <el-form-item label="票据模板" prop="invoiceTemplateId"> | ||||
|             <el-input v-model="formData.invoiceTemplateId" placeholder="请输入票据模板" disabled /> | ||||
|           </el-form-item> | ||||
|         </el-col> | ||||
|       </el-row> | ||||
|        | ||||
|       <el-row> | ||||
|         <el-col :span="8"> | ||||
|           <el-form-item label="违约金比例" prop="penaltyRate"> | ||||
|             <el-input v-model="formData.penaltyRate" placeholder="请输入违约金比例" /> | ||||
|           </el-form-item> | ||||
|         </el-col> | ||||
|         <el-col :span="8"> | ||||
|           <el-form-item label="延期付款利率" prop="latePaymentRate"> | ||||
|             <el-input v-model="formData.latePaymentRate" placeholder="请输入延期付款利率" /> | ||||
|           </el-form-item> | ||||
|         </el-col> | ||||
|         <el-col :span="8"> | ||||
|           <el-form-item label="财务结算方式" prop="settleMethod"> | ||||
|             <el-select v-model="formData.settleMethod" placeholder="请选择财务结算方式"> | ||||
|               <el-option | ||||
|                 v-for="dict in getIntDictOptions('settle_method')" | ||||
|                 :key="dict.value" | ||||
|                 :label="dict.label" | ||||
|                 :value="dict.value" | ||||
|               /> | ||||
|             </el-select> | ||||
|           </el-form-item> | ||||
|         </el-col> | ||||
|       </el-row> | ||||
|        | ||||
|       <el-row> | ||||
|         <el-col :span="8"> | ||||
|           <el-form-item label="最晚付款日期" prop="lastPayDate"> | ||||
|             <el-date-picker | ||||
|               v-model="formData.lastPayDate" | ||||
|               type="date" | ||||
|               value-format="x" | ||||
|               placeholder="选择最晚付款日期" | ||||
|             /> | ||||
|           </el-form-item> | ||||
|         </el-col> | ||||
|         <el-col :span="8"> | ||||
|           <el-form-item label="合同期限(月)" prop="contractTerm"> | ||||
|             <el-input v-model="formData.contractTerm" placeholder="请输入合同期限(月)" /> | ||||
|           </el-form-item> | ||||
|         </el-col> | ||||
|         <el-col :span="8"> | ||||
|           <el-form-item label="报价签约人" prop="signUserId"> | ||||
|             <el-select v-model="formData.signUserId" placeholder="请选择报价签约人" disabled > | ||||
|               <el-option | ||||
|                 v-for="dict in userOptions" | ||||
|                 :key="dict.id" | ||||
|                 :label="dict.nickname" | ||||
|                 :value="dict.id" | ||||
|               /> | ||||
|             </el-select> | ||||
|           </el-form-item> | ||||
|         </el-col> | ||||
|       </el-row> | ||||
|        | ||||
|       <el-row> | ||||
|         <el-col :span="8"> | ||||
|           <el-form-item label="签约人联系电话" prop="signPhoneNumber"> | ||||
|             <el-input v-model="formData.signPhoneNumber" placeholder="请输入签约人联系电话" disabled /> | ||||
|           </el-form-item> | ||||
|         </el-col> | ||||
|         <el-col :span="8"> | ||||
|           <el-form-item label="签约人Email" prop="signEmail"> | ||||
|             <el-input v-model="formData.signEmail" placeholder="请输入签约人Email" disabled /> | ||||
|           </el-form-item> | ||||
|         </el-col> | ||||
|         <el-col :span="8"> | ||||
|           <el-form-item label="签约人微信" prop="signWechat"> | ||||
|             <el-input v-model="formData.signWechat" placeholder="请输入签约人微信" disabled /> | ||||
|           </el-form-item> | ||||
|         </el-col> | ||||
|       </el-row> | ||||
|        | ||||
|       <el-row> | ||||
|         <el-col :span="8"> | ||||
|           <el-form-item label="商机负责人" prop="ownerUserId"> | ||||
|             <el-select v-model="formData.ownerUserId" placeholder="请选择商机负责人" disabled> | ||||
|               <el-option | ||||
|                 v-for="dict in userOptions" | ||||
|                 :key="dict.id" | ||||
|                 :label="dict.nickname" | ||||
|                 :value="dict.id" | ||||
|               /> | ||||
|             </el-select> | ||||
|           </el-form-item> | ||||
|         </el-col> | ||||
|         <el-col :span="8"> | ||||
|           <el-form-item label="拓展人" prop="expanderUserId"> | ||||
|             <el-select v-model="formData.expanderUserId" placeholder="请选择拓展人" disabled> | ||||
|               <el-option | ||||
|                 v-for="dict in userOptions" | ||||
|                 :key="dict.id" | ||||
|                 :label="dict.nickname" | ||||
|                 :value="dict.id" | ||||
|               /> | ||||
|             </el-select> | ||||
|           </el-form-item> | ||||
|         </el-col> | ||||
|         <el-col :span="8"> | ||||
|           <el-form-item label="方案报价人" prop="pricingUserId"> | ||||
|             <el-select v-model="formData.pricingUserId" placeholder="请选择方案报价人" disabled> | ||||
|               <el-option | ||||
|                 v-for="dict in userOptions" | ||||
|                 :key="dict.id" | ||||
|                 :label="dict.nickname" | ||||
|                 :value="dict.id" | ||||
|               /> | ||||
|             </el-select> | ||||
|           </el-form-item> | ||||
|         </el-col> | ||||
|       </el-row> | ||||
|        | ||||
|       <el-row> | ||||
|         <el-col :span="8"> | ||||
|           <el-form-item label="售后维护人" prop="afterSaleUserId"> | ||||
|             <el-select v-model="formData.afterSaleUserId" placeholder="请选择售后维护人"> | ||||
|               <el-option | ||||
|                 v-for="dict in userOptions" | ||||
|                 :key="dict.id" | ||||
|                 :label="dict.nickname" | ||||
|                 :value="dict.id" | ||||
|               /> | ||||
|             </el-select> | ||||
|           </el-form-item> | ||||
|         </el-col> | ||||
|         <el-col :span="8"> | ||||
|           <el-form-item label="协作人" prop="collUserId"> | ||||
|             <el-select v-model="formData.collUserId" placeholder="请选择协作人"> | ||||
|               <el-option | ||||
|                 v-for="dict in userOptions" | ||||
|                 :key="dict.id" | ||||
|                 :label="dict.nickname" | ||||
|                 :value="dict.id" | ||||
|               /> | ||||
|             </el-select> | ||||
|           </el-form-item> | ||||
|         </el-col> | ||||
|       </el-row> | ||||
| 
 | ||||
|       <el-row> | ||||
|         <el-col :span="8"> | ||||
|           <el-form-item label="授信方式" prop="creditMethod" > | ||||
|             <el-select v-model="formData.creditMethod" placeholder="请选择授信方式" disabled> | ||||
|               <el-option | ||||
|                 v-for="dict in getIntDictOptions('credit_method')" | ||||
|                 :key="dict.value" | ||||
|                 :label="dict.label" | ||||
|                 :value="dict.value" | ||||
|               /> | ||||
|             </el-select> | ||||
|           </el-form-item> | ||||
|         </el-col> | ||||
|         <el-col :span="8"> | ||||
|           <el-form-item label="授信计算周期" prop="creditCalcCycle" > | ||||
|             <el-select v-model="formData.creditCalcCycle" placeholder="请选择授信计算周期" disabled> | ||||
|               <el-option | ||||
|                 v-for="dict in getIntDictOptions('credit_calc_cycle')" | ||||
|                 :key="dict.value" | ||||
|                 :label="dict.label" | ||||
|                 :value="dict.value" | ||||
|               /> | ||||
|             </el-select> | ||||
|           </el-form-item> | ||||
|         </el-col> | ||||
|         <el-col :span="8"> | ||||
|           <el-form-item label="授信额度" prop="creditLimit"> | ||||
|             <el-input v-model="formData.creditLimit" placeholder="请输入授信额度" disabled /> | ||||
|           </el-form-item> | ||||
|         </el-col> | ||||
|       </el-row> | ||||
|        | ||||
|       <el-row> | ||||
|         <el-col :span="8"> | ||||
|           <el-form-item label="合作主体" prop="partnerCompanyId"> | ||||
|             <el-select v-model="formData.partnerCompanyId" placeholder="请选择合作主体" disabled > | ||||
|               <el-option | ||||
|                 v-for="dict in deptList" | ||||
|                 :key="dict.id" | ||||
|                 :label="dict.name" | ||||
|                 :value="dict.id" | ||||
|               /> | ||||
|             </el-select> | ||||
|           </el-form-item> | ||||
|         </el-col> | ||||
|         <el-col :span="8"> | ||||
|           <el-form-item label="归属部门" prop="deptId"  > | ||||
|             <el-tree-select | ||||
|               v-model="formData.deptId" | ||||
|               :data="deptTree" | ||||
|               :props="defaultProps" | ||||
|               filterable | ||||
|               disabled | ||||
|               check-strictly | ||||
|               node-key="id" | ||||
|               placeholder="请选择归属部门" | ||||
|             /> | ||||
|           </el-form-item> | ||||
|         </el-col> | ||||
|         <el-col :span="8"> | ||||
|           <el-form-item label="第几次报价" prop="quotationTimes"> | ||||
|             <el-input v-model="formData.quotationTimes" placeholder="请输入第几次报价" /> | ||||
|           </el-form-item> | ||||
|         </el-col> | ||||
|       </el-row> | ||||
| 
 | ||||
|       <el-row> | ||||
|         <el-col :span="12"> | ||||
|           <el-form-item label="合同正文" prop="contractBody"> | ||||
|             <el-input v-model="formData.contractBody" placeholder="请输入合同正文" /> | ||||
|           </el-form-item> | ||||
|         </el-col> | ||||
|         <el-col :span="12"> | ||||
|           <el-form-item label="合同补充协议" prop="contractAgreement"> | ||||
|             <el-input v-model="formData.contractAgreement" placeholder="请输入合同补充协议" /> | ||||
|           </el-form-item> | ||||
|         </el-col> | ||||
|       </el-row> | ||||
| 
 | ||||
|       <el-row> | ||||
|         <el-col :span="8"> | ||||
|           <el-form-item label="线上总金额" prop="onlinePrice"> | ||||
|             <el-input | ||||
|               disabled | ||||
|               v-model="formData.onlinePrice" | ||||
|               placeholder="请输入线上总金额,单位:元"  | ||||
|               :formatter="erpPriceInputFormatter" | ||||
|             /> | ||||
|           </el-form-item> | ||||
|         </el-col> | ||||
|         <el-col :span="8"> | ||||
|           <el-form-item label="线下总金额" prop="offlinePrice"> | ||||
|             <el-input | ||||
|               disabled | ||||
|               v-model="formData.offlinePrice" | ||||
|               placeholder="请输入线下总金额,单位:元"  | ||||
|               :formatter="erpPriceInputFormatter" | ||||
|             /> | ||||
|           </el-form-item> | ||||
|         </el-col> | ||||
|         <el-col :span="8"> | ||||
|           <el-form-item label="总金额" prop="price"> | ||||
|             <el-input | ||||
|               disabled | ||||
|               v-model="formData.totalPrice" | ||||
|               :formatter="erpPriceInputFormatter" | ||||
|             /> | ||||
|           </el-form-item> | ||||
|         </el-col> | ||||
|       </el-row> | ||||
|       <!-- 子表的表单 --> | ||||
|       <ContentWrap> | ||||
|         <el-tabs v-model="subTabsName" class="-mt-15px -mb-10px"> | ||||
|           <el-tab-pane label="产品清单" name="product"> | ||||
|             <ContractProductForm | ||||
|               ref="productFormRef" | ||||
|               :products="formData.products" | ||||
|               :disabled="disabled" | ||||
|             /> | ||||
|           </el-tab-pane> | ||||
|           <el-tab-pane label="合同甲方关联单位" name="contractAAuthorizedCompany"> | ||||
|             <ContractAAuthorizedCompanyForm ref="contractAAuthorizedCompanyFormRef" :contract-id="formData.id" /> | ||||
|           </el-tab-pane> | ||||
|           <el-tab-pane label="合同甲方授权人信息" name="contractAAuthorizedPerson"> | ||||
|             <ContractAAuthorizedPersonForm ref="contractAAuthorizedPersonFormRef" :contract-id="formData.id" /> | ||||
|           </el-tab-pane> | ||||
|           <el-tab-pane label="合同乙方授权人信息" name="contractBAuthorizedPerson"> | ||||
|             <ContractBAuthorizedPersonForm ref="contractBAuthorizedPersonFormRef" :contract-id="formData.id" /> | ||||
|           </el-tab-pane> | ||||
|         </el-tabs> | ||||
|       </ContentWrap> | ||||
|     </el-form> | ||||
|     <div style="text-align: right"> | ||||
|         <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> | ||||
|         <el-button @click="goBack">取 消</el-button> | ||||
|     </div> | ||||
|   </ContentWrap> | ||||
| </template> | ||||
| <script lang="ts" setup> | ||||
| import { getIntDictOptions, DICT_TYPE } from '@/utils/dict' | ||||
| import * as CustomerApi from '@/api/crm/customer' | ||||
| import * as ContractApi from '@/api/crm/contract' | ||||
| import * as ContactApi from '@/api/crm/contact' | ||||
| import * as UserApi from '@/api/system/user' | ||||
| import { QuotationApi,QuotationVO } from '@/api/crm/quotation' | ||||
| import { erpPriceMultiply, erpPriceInputFormatter } from '@/utils' | ||||
| import { useUserStore } from '@/store/modules/user' | ||||
| import ContractProductForm from '@/views/crm/contract/components/ContractProductForm.vue' | ||||
| import ContractAAuthorizedCompanyForm from './components/ContractAAuthorizedCompanyForm.vue' | ||||
| import ContractAAuthorizedPersonForm from './components/ContractAAuthorizedPersonForm.vue' | ||||
| import ContractBAuthorizedPersonForm from './components/ContractBAuthorizedPersonForm.vue' | ||||
| 
 | ||||
| const { t } = useI18n() // 国际化 | ||||
| const message = useMessage() // 消息弹窗 | ||||
| const { proxy }: any = getCurrentInstance(); | ||||
| 
 | ||||
| const dialogVisible = ref(false) // 弹窗的是否展示 | ||||
| const dialogTitle = ref('') // 弹窗的标题 | ||||
| const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 | ||||
| const formType = ref('') // 表单的类型:create - 新增;update - 修改 | ||||
| const formData = ref({ | ||||
|   id: undefined, | ||||
|   name: undefined, | ||||
|   no: undefined, | ||||
|   customerId: undefined, | ||||
|   quotationId: undefined, | ||||
|   invoiceTemplateId: undefined, | ||||
|   processInstanceId: undefined, | ||||
|   auditStatus: undefined, | ||||
|   startTime: undefined, | ||||
|   endTime: undefined, | ||||
|   penaltyRate: undefined, | ||||
|   latePaymentRate: undefined, | ||||
|   settleMethod: undefined, | ||||
|   lastPayDate: undefined, | ||||
|   contractTerm: undefined, | ||||
|   signUserId: undefined, | ||||
|   signPhoneNumber: undefined, | ||||
|   signEmail: undefined, | ||||
|   signWechat: undefined, | ||||
|   offlinePrice: undefined, | ||||
|   onlinePrice: undefined, | ||||
|   ownerUserId: undefined, | ||||
|   expanderUserId: undefined, | ||||
|   pricingUserId: undefined, | ||||
|   afterSaleUserId: undefined, | ||||
|   collUserId: undefined, | ||||
|   totalPrice: undefined, | ||||
|   contractBody: undefined, | ||||
|   contractAgreement: undefined, | ||||
|   creditMethod: undefined, | ||||
|   creditCalcCycle: undefined, | ||||
|   creditLimit: undefined, | ||||
|   partnerCompanyId: undefined, | ||||
|   deptId: undefined, | ||||
|   quotationTimes: undefined, | ||||
|   products: [] | ||||
| }) | ||||
| const formRules = reactive({ | ||||
|   name: [{ required: true, message: '合同名称不能为空', trigger: 'blur' }], | ||||
|   customerId: [{ required: true, message: '客户不能为空', trigger: 'blur' }], | ||||
|   orderDate: [{ required: true, message: '下单日期不能为空', trigger: 'blur' }], | ||||
|   ownerUserId: [{ required: true, message: '负责人不能为空', trigger: 'blur' }] | ||||
| }) | ||||
| const formRef = ref() // 表单 Ref | ||||
| const userOptions = ref<UserApi.UserVO[]>([]) // 用户列表 | ||||
| const customerList = ref([]) // 客户列表的数据 | ||||
| const quotationList = ref<QuotationVO[]>([]) | ||||
| const contactList = ref<ContactApi.ContactVO[]>([]) | ||||
| 
 | ||||
| /** 子表的表单 */ | ||||
| const subTabsName = ref('product') | ||||
| const productFormRef = ref() | ||||
| const contractAAuthorizedCompanyFormRef = ref() | ||||
| const contractAAuthorizedPersonFormRef = ref() | ||||
| const contractBAuthorizedPersonFormRef = ref() | ||||
| 
 | ||||
| /** 计算 discountPrice、totalPrice 价格 */ | ||||
| watch( | ||||
|   () => formData.value, | ||||
|   (val) => { | ||||
|     if (!val) { | ||||
|       return | ||||
|     } | ||||
|     // const totalPrice = val.products.reduce((prev, curr) => prev + curr.totalPrice, 0) | ||||
|     // 赋值 | ||||
|     // formData.value.totalPrice = totalPrice | ||||
|   }, | ||||
|   { deep: true } | ||||
| ) | ||||
| 
 | ||||
| /** 打开弹窗 */ | ||||
| const open = async (type: string) => { | ||||
|   if (type) { | ||||
|     formLoading.value = true | ||||
|     try { | ||||
|       formData.value = await ContractApi.getContract(type) | ||||
|     } finally { | ||||
|       formLoading.value = false | ||||
|     } | ||||
|   } | ||||
|    | ||||
| } | ||||
| defineExpose({ open }) // 提供 open 方法,用于打开弹窗 | ||||
| 
 | ||||
| /** 提交表单 */ | ||||
| const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 | ||||
| const submitForm = async () => { | ||||
|   // 校验表单 | ||||
|   if (!formRef) return | ||||
|   const valid = await formRef.value.validate() | ||||
|   if (!valid) return | ||||
|   // 提交请求 | ||||
|   formLoading.value = true | ||||
|   productFormRef.value.validate() | ||||
|   try { | ||||
|     const data = unref(formData.value) as unknown as ContractApi.ContractVO | ||||
|     // 拼接子表的数据 | ||||
|     data.contractAAuthorizedCompanys = contractAAuthorizedCompanyFormRef.value.getData() | ||||
|     data.contractAAuthorizedPersons = contractAAuthorizedPersonFormRef.value.getData() | ||||
|     data.contractBAuthorizedPersons = contractBAuthorizedPersonFormRef.value.getData() | ||||
|     if (!formType.value ) { | ||||
|       await ContractApi.createContract(data) | ||||
|       message.success(t('common.createSuccess')) | ||||
|     } else { | ||||
|       await ContractApi.updateContract(data) | ||||
|       message.success(t('common.updateSuccess')) | ||||
|     } | ||||
|     dialogVisible.value = false | ||||
|     // 发送操作成功的事件 | ||||
|     emit('success') | ||||
|     goBack() | ||||
|   } finally { | ||||
|     formLoading.value = false | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| const goBack = ()=> { | ||||
|   proxy.$router.go(-1) | ||||
| } | ||||
| 
 | ||||
| /** 重置表单 */ | ||||
| const resetForm = () => { | ||||
|   formData.value = { | ||||
|     id: undefined, | ||||
|     name: undefined, | ||||
|     no: undefined, | ||||
|     customerId: undefined, | ||||
|     quotationId: undefined, | ||||
|     invoiceTemplateId: undefined, | ||||
|     processInstanceId: undefined, | ||||
|     auditStatus: undefined, | ||||
|     startTime: undefined, | ||||
|     endTime: undefined, | ||||
|     penaltyRate: undefined, | ||||
|     latePaymentRate: undefined, | ||||
|     settleMethod: undefined, | ||||
|     lastPayDate: undefined, | ||||
|     contractTerm: undefined, | ||||
|     signUserId: undefined, | ||||
|     signPhoneNumber: undefined, | ||||
|     signEmail: undefined, | ||||
|     signWechat: undefined, | ||||
|     offlinePrice: undefined, | ||||
|     onlinePrice: undefined, | ||||
|     ownerUserId: undefined, | ||||
|     expanderUserId: undefined, | ||||
|     pricingUserId: undefined, | ||||
|     afterSaleUserId: undefined, | ||||
|     collUserId: undefined, | ||||
|     totalPrice: undefined, | ||||
|     contractBody: undefined, | ||||
|     contractAgreement: undefined, | ||||
|     creditMethod: undefined, | ||||
|     creditCalcCycle: undefined, | ||||
|     creditLimit: undefined, | ||||
|     partnerCompanyId: undefined, | ||||
|     deptId: undefined, | ||||
|     quotationTimes: undefined, | ||||
|     products: [] | ||||
|   } | ||||
|   formRef.value?.resetFields() | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** 处理商机变化 */ | ||||
| const handleQuotationChange = async (quotationId: number) => { | ||||
|   if (!quotationId) return | ||||
|   try { | ||||
|     const quotation = await QuotationApi.getQuotation(quotationId) | ||||
|     formData.value.products = quotation.products; | ||||
|     formData.value.customerId = quotation.customerId;  | ||||
| 
 | ||||
|     formData.value.invoiceTemplateId = quotation.invoiceTemplateId;  | ||||
| 
 | ||||
|     formData.value.ownerUserId = quotation.ownerUserId; | ||||
|     formData.value.expanderUserId = quotation.expanderUserId; | ||||
|     formData.value.pricingUserId = quotation.pricingUserId; | ||||
|     formData.value.signUserId = quotation.signUserId; | ||||
|     formData.value.signPhoneNumber = quotation.signPhoneNumber; | ||||
|     formData.value.signEmail = quotation.signEmail; | ||||
|     formData.value.signWechat = quotation.signWechat; | ||||
| 
 | ||||
|     formData.value.partnerCompanyId = quotation.partnerCompanyId; | ||||
| 
 | ||||
|     formData.value.creditLimit = quotation.creditLimit; | ||||
|     formData.value.creditMethod = quotation.creditMethod; | ||||
|     formData.value.creditCalcCycle = quotation.creditCalcCycle; | ||||
| 
 | ||||
|     formData.value.deptId = quotation.deptId; | ||||
|     formData.value.offlinePrice = quotation.offlinePrice; | ||||
|     formData.value.onlinePrice = quotation.onlinePrice; | ||||
|     formData.value.totalPrice = quotation.totalPrice; | ||||
|      | ||||
|      // 🔁 自动加载客户详情 | ||||
|      await onCustomerChange(quotation.customerId); | ||||
|   } catch (err) { | ||||
|   } finally { | ||||
| 
 | ||||
|   } | ||||
|    | ||||
| } | ||||
| 
 | ||||
| const onCustomerChange = async (customerId: string) => { | ||||
|   if (!customerId) return; | ||||
| 
 | ||||
|   try { | ||||
|     formLoading.value = true; | ||||
|     const customerRes = await CustomerApi.getCustomer(customerId); | ||||
|     formData.value.cooperationType = customerRes.cooperationType; | ||||
|     formData.value.companyType = customerRes.companyType; | ||||
|     formData.value.listingStatus = customerRes.listingStatus; | ||||
|     formData.value.financingInfo = customerRes.financingInfo; | ||||
|     formData.value.paidInCapital = customerRes.paidInCapital; | ||||
|     formData.value.insuredCount = customerRes.insuredCount; | ||||
|     formData.value.establishmentDate = customerRes.establishmentDate; | ||||
|     formData.value.enterpriseType = customerRes.enterpriseType; | ||||
|     formData.value.businessStatus = customerRes.businessStatus; | ||||
|     formData.value.defendantRecord = customerRes.defendantRecord; | ||||
|     formData.value.businessAbnormal = customerRes.businessAbnormal; | ||||
|     formData.value.equityPledge = customerRes.equityPledge; | ||||
|     formData.value.dishonestRecord = customerRes.dishonestRecord; | ||||
|     formData.value.financingRecord = customerRes.financingRecord; | ||||
|     formData.value.enforcementRecord = customerRes.enforcementRecord; | ||||
|   } catch (err) { | ||||
|     console.error('获取客户详情失败:', err); | ||||
|   } finally { | ||||
|     formLoading.value = false; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** 动态获取客户联系人 */ | ||||
| const getContactOptions = computed(() => | ||||
|   contactList.value.filter((item) => item.customerId == formData.value.customerId) | ||||
| ) | ||||
| 
 | ||||
| const route = useRoute(); | ||||
| onMounted(async () => { | ||||
|   formType.value = route.query.id; | ||||
| 
 | ||||
|   if (formType.value) open(formType.value) | ||||
| 
 | ||||
|   // 获得客户列表 | ||||
|   customerList.value = await CustomerApi.getCustomerSimpleList() | ||||
|   // 获得用户列表 | ||||
|   userOptions.value = await UserApi.getSimpleUserList() | ||||
|   // 获得报价列表 | ||||
|   quotationList.value = await QuotationApi.getSimpleQuotationList() | ||||
| 
 | ||||
|   // 默认新建时选中自己 | ||||
|   // if (formType.value === 'create') { | ||||
|   //   formData.value.ownerUserId = useUserStore().getUser.id | ||||
|   // } | ||||
|   // 获取联系人 | ||||
|   contactList.value = await ContactApi.getSimpleContactList() | ||||
| }); | ||||
| </script> | ||||
|  | @ -1,5 +1,5 @@ | |||
| <template> | ||||
|   <Dialog v-model="dialogVisible" :title="dialogTitle" width="1280"> | ||||
|   <ContentWrap class="mt-10px"> | ||||
|     <el-form | ||||
|       ref="formRef" | ||||
|       v-loading="formLoading" | ||||
|  | @ -359,11 +359,11 @@ | |||
|         </el-tabs> | ||||
|       </ContentWrap> | ||||
|     </el-form> | ||||
|     <template #footer> | ||||
|       <el-button :disabled="formLoading" type="primary" @click="submitForm">保存</el-button> | ||||
|       <el-button @click="dialogVisible = false">取 消</el-button> | ||||
|     </template> | ||||
|   </Dialog> | ||||
|     <div style="text-align: right"> | ||||
|         <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> | ||||
|         <el-button @click="goBack">取 消</el-button> | ||||
|     </div> | ||||
|   </ContentWrap> | ||||
| </template> | ||||
| <script lang="ts" setup> | ||||
| import { getIntDictOptions, DICT_TYPE } from '@/utils/dict' | ||||
|  | @ -381,6 +381,7 @@ import ContractBAuthorizedPersonForm from './components/ContractBAuthorizedPerso | |||
| 
 | ||||
| const { t } = useI18n() // 国际化 | ||||
| const message = useMessage() // 消息弹窗 | ||||
| const { proxy }: any = getCurrentInstance(); | ||||
| 
 | ||||
| const dialogVisible = ref(false) // 弹窗的是否展示 | ||||
| const dialogTitle = ref('') // 弹窗的标题 | ||||
|  | @ -458,33 +459,16 @@ watch( | |||
| ) | ||||
| 
 | ||||
| /** 打开弹窗 */ | ||||
| const open = async (type: string, id?: number) => { | ||||
|   dialogVisible.value = true | ||||
|   dialogTitle.value = t('action.' + type) | ||||
|   formType.value = type | ||||
|   resetForm() | ||||
|   // 修改时,设置数据 | ||||
|   if (id) { | ||||
| const open = async (type: string) => { | ||||
|   if (type) { | ||||
|     formLoading.value = true | ||||
|     try { | ||||
|       formData.value = await ContractApi.getContract(id) | ||||
|       formData.value = await ContractApi.getContract(type) | ||||
|     } finally { | ||||
|       formLoading.value = false | ||||
|     } | ||||
|   } | ||||
|   // 获得客户列表 | ||||
|   customerList.value = await CustomerApi.getCustomerSimpleList() | ||||
|   // 获得用户列表 | ||||
|   userOptions.value = await UserApi.getSimpleUserList() | ||||
|   // 获得报价列表 | ||||
|   quotationList.value = await QuotationApi.getSimpleQuotationList() | ||||
|    | ||||
|   // 默认新建时选中自己 | ||||
|   // if (formType.value === 'create') { | ||||
|   //   formData.value.ownerUserId = useUserStore().getUser.id | ||||
|   // } | ||||
|   // 获取联系人 | ||||
|   contactList.value = await ContactApi.getSimpleContactList() | ||||
| } | ||||
| defineExpose({ open }) // 提供 open 方法,用于打开弹窗 | ||||
| 
 | ||||
|  | @ -504,7 +488,7 @@ const submitForm = async () => { | |||
|     data.contractAAuthorizedCompanys = contractAAuthorizedCompanyFormRef.value.getData() | ||||
|     data.contractAAuthorizedPersons = contractAAuthorizedPersonFormRef.value.getData() | ||||
|     data.contractBAuthorizedPersons = contractBAuthorizedPersonFormRef.value.getData() | ||||
|     if (formType.value === 'create') { | ||||
|     if (!formType.value ) { | ||||
|       await ContractApi.createContract(data) | ||||
|       message.success(t('common.createSuccess')) | ||||
|     } else { | ||||
|  | @ -514,11 +498,16 @@ const submitForm = async () => { | |||
|     dialogVisible.value = false | ||||
|     // 发送操作成功的事件 | ||||
|     emit('success') | ||||
|     goBack() | ||||
|   } finally { | ||||
|     formLoading.value = false | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| const goBack = ()=> { | ||||
|   proxy.$router.go(-1) | ||||
| } | ||||
| 
 | ||||
| /** 重置表单 */ | ||||
| const resetForm = () => { | ||||
|   formData.value = { | ||||
|  | @ -634,4 +623,25 @@ const onCustomerChange = async (customerId: string) => { | |||
| const getContactOptions = computed(() => | ||||
|   contactList.value.filter((item) => item.customerId == formData.value.customerId) | ||||
| ) | ||||
| 
 | ||||
| const route = useRoute(); | ||||
| onMounted(async () => { | ||||
|   formType.value = route.query.id; | ||||
| 
 | ||||
|   if (formType.value) open(formType.value) | ||||
| 
 | ||||
|   // 获得客户列表 | ||||
|   customerList.value = await CustomerApi.getCustomerSimpleList() | ||||
|   // 获得用户列表 | ||||
|   userOptions.value = await UserApi.getSimpleUserList() | ||||
|   // 获得报价列表 | ||||
|   quotationList.value = await QuotationApi.getSimpleQuotationList() | ||||
| 
 | ||||
|   // 默认新建时选中自己 | ||||
|   // if (formType.value === 'create') { | ||||
|   //   formData.value.ownerUserId = useUserStore().getUser.id | ||||
|   // } | ||||
|   // 获取联系人 | ||||
|   contactList.value = await ContactApi.getSimpleContactList() | ||||
| }); | ||||
| </script> | ||||
|  |  | |||
|  | @ -53,7 +53,7 @@ | |||
|           <Icon class="mr-5px" icon="ep:refresh" /> | ||||
|           重置 | ||||
|         </el-button> | ||||
|         <el-button v-hasPermi="['crm:contract:create']" type="primary" @click="openForm('create')"> | ||||
|         <el-button v-hasPermi="['crm:contract:create']" type="primary" @click="openFormAdd"> | ||||
|           <Icon class="mr-5px" icon="ep:plus" /> | ||||
|           新增 | ||||
|         </el-button> | ||||
|  | @ -204,7 +204,7 @@ | |||
|             v-hasPermi="['crm:contract:update']" | ||||
|             link | ||||
|             type="primary" | ||||
|             @click="openForm('update', scope.row.id)" | ||||
|             @click="openFormEdit(scope.row)" | ||||
|           > | ||||
|             编辑 | ||||
|           </el-button> | ||||
|  | @ -217,6 +217,15 @@ | |||
|           > | ||||
|             提交审核 | ||||
|           </el-button> | ||||
|           <el-button | ||||
|             v-if="scope.row.auditStatus === 0" | ||||
|             v-hasPermi="['crm:contract:update']" | ||||
|             link | ||||
|             type="primary" | ||||
|             @click="handleChange(scope.row)" | ||||
|           > | ||||
|             合同变更 | ||||
|           </el-button> | ||||
|           <el-button | ||||
|             v-else | ||||
|             link | ||||
|  | @ -254,14 +263,11 @@ | |||
|     /> | ||||
|   </ContentWrap> | ||||
| 
 | ||||
|   <!-- 表单弹窗:添加/修改 --> | ||||
|   <ContractForm ref="formRef" @success="getList" /> | ||||
| </template> | ||||
| <script lang="ts" setup> | ||||
| import { dateFormatter, dateFormatter2 } from '@/utils/formatTime' | ||||
| import download from '@/utils/download' | ||||
| import * as ContractApi from '@/api/crm/contract' | ||||
| import ContractForm from './ContractForm.vue' | ||||
| import { DICT_TYPE } from '@/utils/dict' | ||||
| import { erpPriceInputFormatter, erpPriceTableColumnFormatter } from '@/utils' | ||||
| import * as CustomerApi from '@/api/crm/customer' | ||||
|  | @ -321,8 +327,22 @@ const resetQuery = () => { | |||
| 
 | ||||
| /** 添加/修改操作 */ | ||||
| const formRef = ref() | ||||
| const openForm = (type: string, id?: number) => { | ||||
|   formRef.value.open(type, id) | ||||
| 
 | ||||
| const openFormEdit =  (row: Object) => { | ||||
|    | ||||
|   push({ name: 'CrmContractEdit', query: { id: row.id} }) | ||||
| } | ||||
| const openFormAdd =  () => { | ||||
|   push({ name: 'CrmContractAdd' }) | ||||
| } | ||||
| 
 | ||||
| const openFormDetail = (row: Object) => { | ||||
|    | ||||
|   push({ name: 'CrmContractDetail', query: { id: row.id } }) | ||||
| } | ||||
| const handleChange = (row: Object) => { | ||||
|   push({ name: 'CrmContractChange', query: { id: row.id } }) | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| /** 删除按钮操作 */ | ||||
|  | @ -392,4 +412,7 @@ onMounted(async () => { | |||
|   await getList() | ||||
|   customerList.value = await CustomerApi.getCustomerSimpleList() | ||||
| }) | ||||
| onActivated(()=>{ | ||||
|   getList() | ||||
| }) | ||||
| </script> | ||||
|  |  | |||
|  | @ -8,11 +8,7 @@ | |||
|       v-loading="formLoading" | ||||
|     > | ||||
|       <el-row> | ||||
|         <el-col :span="8"> | ||||
|           <el-form-item label="报价单编号" prop="no"> | ||||
|             <el-input v-model="formData.no" placeholder="请输入报价单编号" /> | ||||
|           </el-form-item> | ||||
|         </el-col> | ||||
|          | ||||
| 
 | ||||
|         <el-col :span="8"> | ||||
|           <el-form-item label="选择商机" prop="businessId"> | ||||
|  | @ -26,6 +22,11 @@ | |||
|             </el-select> | ||||
|           </el-form-item> | ||||
|         </el-col> | ||||
|         <el-col :span="8" v-if="formType"> | ||||
|           <el-form-item label="报价单编号" prop=""> | ||||
|             <el-input v-model="formData.no" disabled placeholder="自动获取" /> | ||||
|           </el-form-item> | ||||
|         </el-col> | ||||
|       </el-row> | ||||
|        | ||||
|       <el-row> | ||||
|  | @ -363,8 +364,6 @@ import * as CustomerApi from '@/api/crm/customer' | |||
| import * as UserApi from '@/api/system/user' | ||||
| import * as DeptApi from '@/api/system/dept' | ||||
| import * as BusinessApi from '@/api/crm/business' | ||||
| import {BillTemplateApi } from '@/api/crm/billtemplate' | ||||
| import { erpPriceMultiply, erpPriceInputFormatter } from '@/utils' | ||||
| 
 | ||||
| /** CRM 方案报价 表单 */ | ||||
| defineOptions({ name: 'QuotationForm' }) | ||||
|  |  | |||
|  | @ -295,4 +295,7 @@ onMounted(async () => { | |||
|   // 获得用户列表 | ||||
|   userOptions.value = await UserApi.getSimpleUserList() | ||||
| }) | ||||
| onActivated(()=>{ | ||||
|   getList() | ||||
| }) | ||||
| </script> | ||||
		Loading…
	
		Reference in New Issue
	
	 zy
						zy