瀏覽代碼

feat: 新增 签订合同、发起分包与外包合同流程,新增编辑合同接口

hotchicken1996 1 年之前
父節點
當前提交
322f861a4f

+ 243 - 0
client/src/interface/contract.ts

@@ -4,3 +4,246 @@ export type ContractId = string
 export interface ContractQueryParams {
   contractId: ContractId
 }
+
+/**
+ * 合同数据类型
+ */
+export interface Contract {
+  /**
+   * 合同费用状态,{ 2,"未付清"},{ 3,"已付清"},{ 4,"手动设置已付清"}
+   */
+  amountStatus?: number
+  /**
+   * 受托方id
+   */
+  assigneeId?: string
+  /**
+   * 受托方
+   */
+  assigneeName?: string
+  /**
+   * 挂靠管理费比例
+   */
+  attachManageRatio?: number | null
+  /**
+   * 合同分类, { 1,"采购合同"},{ 2,"技术服务合同"},{ 3,"技贸合同"},{ 4,"协议合同"},{ 5,"其他"}
+   */
+  category?: number
+  /**
+   * 分包和外包合同
+   */
+  children?: ExtraConstract[]
+  /**
+   * 委托方id
+   */
+  clientId?: string
+  /**
+   * 委托方
+   */
+  clientName?: string
+  /**
+   * 合同金额
+   */
+  contractAmount?: number
+  /**
+   * 合同余额
+   */
+  contractBalance?: number
+  /**
+   * 净合同额
+   */
+  contractNetAmount?: number
+  /**
+   * 合同编号
+   */
+  contractNumber?: string
+  /**
+   * 合同拿回日期
+   */
+  contractOff?: string
+  /**
+   * 合同拿出日期
+   */
+  contractOn?: string
+  /**
+   * 客户联系人
+   */
+  customerContact?: string
+  /**
+   * 客户联系人id
+   */
+  customerContactId?: string
+  id: null | string
+  /**
+   * 流程id
+   */
+  instanceId?: string
+  /**
+   * 已开票金额
+   */
+  invoicedAmount?: number
+  /**
+   * 是否已签订,{ 0,"未签"},{1,"已签"},{ 2,"待拿回"},{ 3,"不签"}
+   */
+  isSign?: number
+  /**
+   * 合同主类型,1-规划类 2-数据工程类 3-软件类 4-采购类
+   */
+  mainType?: string
+  /**
+   * 合同名称
+   */
+  name?: string
+  /**
+   * 付款条件
+   */
+  paymentTerms?: string
+  /**
+   * 预估合同额
+   */
+  planContractAmount?: number
+  /**
+   * 项目id
+   */
+  projectId?: string
+  /**
+   * 质保金
+   */
+  qualityMoney?: number
+  /**
+   * 质保金状态
+   */
+  qualityMoneyStatus?: number
+  /**
+   * 应收账款
+   */
+  receivableAmount?: number
+  /**
+   * 已回款金额
+   */
+  receivedAmount?: number
+  /**
+   * 合同次类型,1-普通 2-技贸 3-入围 4-补充协议/变更 5-分包 6-外包 7-采购
+   */
+  secondType?: number
+  /**
+   * 签订方式,1-跟单 2-半开拓 3-开拓
+   */
+  signWay?: number
+  /**
+   * 税率与金额_不含税总额
+   */
+  taxBhsze?: number
+  /**
+   * 税率与金额_含税金额_6%服务
+   */
+  taxHsjeFw?: number
+  /**
+   * 税率与金额_含税金额_0%技术开发
+   */
+  taxHsjeJskf?: number
+  /**
+   * 税率与金额_含税金额_13%软件产品
+   */
+  taxHsjeRjcp?: number
+  /**
+   * 税率与金额_含税金额_小计
+   */
+  taxHsjeTotal?: number
+  /**
+   * 税率与金额_含税金额_13%硬件(平板)
+   */
+  taxHsjeYj?: number
+  /**
+   * 税率与金额_软件著作权
+   */
+  taxSoftpatent?: string
+  /**
+   * 税率与金额_综合税率
+   */
+  taxZhsl?: number
+}
+
+export interface ExtraConstract {
+  /**
+   * 合同费用状态
+   */
+  amountStatus?: number
+  /**
+   * 申请人id
+   */
+  applicantId?: string
+  /**
+   * 申请人
+   */
+  applicantName?: string
+  /**
+   * 受托方id
+   */
+  assigneeId?: string
+  /**
+   * 受托方
+   */
+  assigneeName?: string
+  /**
+   * 委托方id
+   */
+  clientId?: string
+  /**
+   * 委托方
+   */
+  clientName?: string
+  /**
+   * 公司认定金额
+   */
+  confirmAmount?: number
+  /**
+   * 合同余额
+   */
+  contractBalance?: number
+  /**
+   * 合同编号
+   */
+  contractNumber?: string
+  /**
+   * 合同拿回日期
+   */
+  contractOff?: string
+  /**
+   * 合同拿出日期
+   */
+  contractOn?: string
+  /**
+   * 合同类型,1-主合同 2-分包合同 3-外包合同
+   */
+  'contractType;'?: number
+  /**
+   * 是否已签订
+   */
+  isSign?: number
+  parentId?: string
+  /**
+   * 付款条件
+   */
+  paymentTerms?: string
+  /**
+   * 采购内容需求
+   */
+  purchaseRequirements?: string
+  /**
+   * 已回款金额
+   */
+  receivedAmount?: number
+  /**
+   * 分包费
+   */
+  subAmount?: number
+  /**
+   * 分包理由
+   */
+  subReason?: string
+  /**
+   * 分包费用承担方式
+   */
+  subShareWay?: number
+}

+ 72 - 2
client/src/service/contract.ts

@@ -1,12 +1,26 @@
 import request from '@/config/axios'
-import { ContractId } from '@/interface/contract'
+import { Contract, ContractId } from '@/interface/contract'
 import { ProjectId } from '@/interface/project'
 
+/**
+ * 合同详情(无分包数据)
+ * @param contractId
+ */
+export const getContractsById = async (contractId: ContractId): Promise<Contract> => {
+  return await request.get(
+    {
+      url: '/contract',
+      params: { contractId }
+    },
+    '/business'
+  )
+}
+
 /**
  * 合同详情与分包合同列表
  * @param projectId
  */
-export const getContractsByProject = async (projectId: ProjectId) => {
+export const getContractsByProject = async (projectId: ProjectId): Promise<Contract> => {
   return await request.get(
     {
       url: '/contract-with-children',
@@ -16,6 +30,20 @@ export const getContractsByProject = async (projectId: ProjectId) => {
   )
 }
 
+/**
+ * 编辑保存合同信息
+ * @param contract
+ */
+export const putContract = async (contract: Contract) => {
+  return await request.put(
+    {
+      url: '/contract',
+      data: contract
+    },
+    '/business'
+  )
+}
+
 /**
  * 合同里程碑
  * @param contractId
@@ -71,3 +99,45 @@ export const getContractSharingList = async (contractId: ContractId) => {
     '/business'
   )
 }
+
+/**
+ * 发起分包合同申请
+ * @param contractId
+ */
+export const startSubcontract = async (contractId: ContractId) => {
+  return await request.get(
+    {
+      url: '/subcontract/process',
+      params: { contractId }
+    },
+    '/business'
+  )
+}
+
+/**
+ * 发起外包合同申请
+ * @param contractId
+ */
+export const startOutsourcing = async (contractId: ContractId) => {
+  return await request.get(
+    {
+      url: '/outsourcing/process',
+      params: { contractId }
+    },
+    '/business'
+  )
+}
+
+/**
+ * 发起合同签订
+ * @param projectId
+ */
+export const startContractSign = async (projectId: ProjectId) => {
+  return await request.get(
+    {
+      url: '/contract/process',
+      params: { projectId }
+    },
+    '/business'
+  )
+}

+ 3 - 0
client/src/utils/flow.ts

@@ -0,0 +1,3 @@
+export const openFlow = (flowPath: string): void => {
+  window.open(flowPath)
+}

+ 11 - 0
client/src/views/OaSystem/projectCenter/projectDetail/components/xmht/ContractReturnedMoney.vue

@@ -13,6 +13,17 @@ const { data: contractRMoneyList } = useQuery(
   [getContractReturnedMoneyList.name, unref(contractId)],
   async () => await getContractReturnedMoneyList(unref(contractId))
 )
+
+const invoiceTypeMap = {
+  '1': '增值税专用发票',
+  '2': '增值税普通发票',
+  '3': '服务业通用机打发票',
+  '4': '统一收款收据'
+}
+const invoiceTypeFilter: (val: number | string) => string = (val: number | string): string => {
+  if (!val) return ''
+  return invoiceTypeMap[val.toString()]
+}
 </script>
 
 <template>

+ 3 - 2
client/src/views/OaSystem/projectCenter/projectDetail/components/xmht/index.scss

@@ -62,6 +62,7 @@
             margin-left: 20px;
             color: #2E77E6;
             font-size: 18px;
+            cursor: pointer;
           }
         }
       }
@@ -97,7 +98,7 @@
           }
         }
         &.tableLineBox {
-          
+
           table {
             width: 100%;
             border-collapse: collapse;
@@ -138,4 +139,4 @@
       margin-right: 20px;
     }
   }
-}
+}

+ 57 - 70
client/src/views/OaSystem/projectCenter/projectDetail/components/xmht/index.vue

@@ -28,10 +28,11 @@
         <div class="tableBox tableBox—first">
           <h4><i class="icon"></i>基本信息</h4>
           <ul>
-            <li>编辑合同</li>
+            <li v-if="editor === false" @click="handleEdit">编辑合同</li>
+            <li v-else @click="saveContractHandle">保存合同</li>
             <li>用款申请</li>
-            <li>分包申请</li>
-            <li>外包申请</li>
+            <li @click="handleStartSubcontract">分包申请</li>
+            <li @click="handleStartOutsourcing">外包申请</li>
           </ul>
           <table>
             <tr>
@@ -293,17 +294,32 @@
   </div>
 </template>
 <script setup lang="ts">
-import request from '@/config/axios'
+import { useRoute } from 'vue-router'
 import UserOrgTree from '@/views/OaSystem/components/UserOrgTree/index.vue'
 import ContractMilestone from '@/views/OaSystem/projectCenter/projectDetail/components/xmht/ContractMilestone.vue'
 import ContractReturnedMoney from '@/views/OaSystem/projectCenter/projectDetail/components/xmht/ContractReturnedMoney.vue'
 import ContractSharing from '@/views/OaSystem/projectCenter/projectDetail/components/xmht/ContractSharing.vue'
+import {
+  getContractsByProject,
+  putContract,
+  startOutsourcing,
+  startSubcontract
+} from '@/service/contract'
+import { useQuery, useMutation } from '@tanstack/vue-query'
+import { ref } from 'vue'
+import { openFlow } from '@/utils/flow'
 
 defineOptions({ name: 'XmhtComp' })
 const _mainProjectId: any = useRoute().query.id
 // 合同id ??是否存在
 const _toContractId = useRoute().query.contractId
 const editor = ref<Boolean>(false)
+const contractDetail = ref()
+
+const handleEdit = () => {
+  console.log('handleEdit: ')
+  editor.value = true
+}
 
 /**
  * 切换子项目信息
@@ -312,81 +328,52 @@ const contractInfoIndex = ref<number>(0)
 const switchContractInfo = (item: any, key: number): void => {
   contractInfoIndex.value = key
 }
+
 /***
  * 查询主合同和子合同详情数据
  * **/
-const contractDetail = ref({
-  id: '',
-  children: [] as any
-})
-
-watch(contractDetail, () => {
-  console.log('contractDetail change: ', contractDetail)
-})
-
-function queryContractWithChildByList(): void {
-  const urlApi = `/contract-with-children`
-  const sendData = {
-    projectId: _mainProjectId
-  }
-  request.get({ url: urlApi, params: sendData }, '/business').then((resultData) => {
-    // contractDetail.value = resultData
-    console.log('queryContractWithChildByList: ', resultData)
-    contractDetail.value = { id: resultData['id'] ?? '', children: [{}] }
-    if (resultData) {
-      // queryContractMilestoneByList(resultData['id'])
-      // queryContractRMoneyByList(resultData['id'])
-      // queryContractPaymentByList(resultData['id'])
-      // queryContractSharingByList(resultData['id'])
+const { refetch } = useQuery(
+  [getContractsByProject.name, unref(_mainProjectId)],
+  async () => await getContractsByProject(unref(_mainProjectId)),
+  {
+    onSuccess: (tData) => {
+      contractDetail.value = tData
     }
-  })
-}
-
-function queryContract(): void {
-  const urlApi = `/contract`
-  const sendData = {
-    id: _toContractId
   }
-  request.get({ url: urlApi, params: sendData }, '/business').then((resultData) => {
-    contractDetail.value = resultData
-    // queryContractMilestoneByList(resultData['id'])
-    // queryContractRMoneyByList(resultData['id'])
-    // queryContractPaymentByList(resultData['id'])
-    // queryContractSharingByList(resultData['id'])
-  })
-}
-
-if (_toContractId) {
-  queryContract()
-} else {
-  queryContractWithChildByList()
-}
+)
 
-//@ts-ignore
-const invoiceTypeMap = {
-  '1': '增值税专用发票',
-  '2': '增值税普通发票',
-  '3': '服务业通用机打发票',
-  '4': '统一收款收据'
-}
-const invoiceTypeFilter: (val: number | string) => string = (val: number | string): string => {
-  if (!val) return ''
-  return invoiceTypeMap[val.toString()]
-}
 /**
  * 编辑保存合同信息
  * **/
-const saveContractHandle = (): void => {
-  const urlApi = `/contract`
-  request.put({ url: urlApi, data: contractDetail.value }, '/business').then((resultData) => {
-    if (resultData) {
-      ElMessage({
-        message: '保存合同成功',
-        type: 'success'
-      })
-    }
-  })
-}
+const { mutate: saveContract } = useMutation(putContract, {
+  onMutate: () => {
+    editor.value = false
+  },
+  onSuccess: () => {
+    void refetch()
+    ElMessage({
+      message: '保存合同成功',
+      type: 'success'
+    })
+  }
+})
+const saveContractHandle = () => saveContract(contractDetail.value)
+
+/**
+ * 发起分包合同申请
+ */
+const { mutate: startSubcontractMutate } = useMutation(startSubcontract, {
+  onSuccess: (data) => openFlow(data)
+})
+const handleStartSubcontract = () => startSubcontractMutate(contractDetail.value.id)
+
+/**
+ * 发起外合同申请
+ */
+const { mutate: startOutsourcingMutate } = useMutation(startOutsourcing, {
+  onSuccess: (data) => openFlow(data)
+})
+const handleStartOutsourcing = () => startOutsourcingMutate(contractDetail.value.id)
 </script>
 <style lang="scss" scoped>
 @import './index.scss';

+ 24 - 12
client/src/views/OaSystem/projectCenter/projectDetail/projectDetail.vue

@@ -11,7 +11,7 @@
         </div>
         <ul>
           <li @click="editorProject">{{ !isEditorProject ? '编辑' : '保存' }}</li>
-          <li>合同签订</li>
+          <li v-if="projectDetail['isSign'] === 1" @click="handleStartContractSign">合同签订</li>
           <li @click="addSubProject">添加子项目</li>
           <li>验收</li>
           <li>结项</li>
@@ -21,18 +21,18 @@
       <div>
         <ul>
           <li @click="switchComponent(XmxxComp, 0)" :class="currentIndex === 0 ? 'active' : ''"
-            ><i class="icon"></i>项目信息</li
-          >
+            ><i class="icon"></i>项目信息
+          </li>
           <!-- v-if="projectDetail['isSign'] === 1" -->
           <li @click="switchComponent(XmhtComp, 1)" :class="currentIndex === 1 ? 'active' : ''"
-            ><i class="icon"></i>项目合同</li
-          >
+            ><i class="icon"></i>项目合同
+          </li>
           <li @click="switchComponent(XmcbComp, 2)" :class="currentIndex === 2 ? 'active' : ''"
-            ><i class="icon"></i>项目成本</li
-          >
+            ><i class="icon"></i>项目成本
+          </li>
           <li @click="switchComponent(FjclComp, 3)" :class="currentIndex === 3 ? 'active' : ''"
-            ><i class="icon"></i>附件材料</li
-          >
+            ><i class="icon"></i>附件材料
+          </li>
         </ul>
         <div class="projectInfo">
           <p>
@@ -70,9 +70,13 @@ const dynamicRef = shallowRef<Component>()
 const XmxxComp = defineAsyncComponent(() => {
   return import('./components/xmxx/index.vue')
 })
-const XmhtComp = defineAsyncComponent(() => {
-  return import('./components/xmht/index.vue')
-})
+import XmhtComp from './components/xmht/index.vue'
+import { startContractSign, startOutsourcing } from '@/service/contract'
+import { openFlow } from '@/utils/flow'
+import { useMutation } from '@tanstack/vue-query'
+import { ContractId } from '@/interface/contract'
+import { ProjectId } from '@/interface/project'
+
 const XmcbComp = defineAsyncComponent(() => {
   return import('./components/xmcb/index.vue')
 })
@@ -122,6 +126,14 @@ const editorProject: () => void = (): void => {
   //@ts-ignore
   dynamicRef.value.saveProjectHandle()
 }
+
+/**
+ * 发起合同签订
+ */
+const { mutate: startContractSignMutate } = useMutation(startContractSign, {
+  onSuccess: (data) => openFlow(data)
+})
+const handleStartContractSign = () => startContractSignMutate(query.id as ProjectId)
 </script>
 <style lang="scss" scoped>
 @import './projectDetail.scss';