projectDetail.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. <template>
  2. <div class="_ProjectDetail">
  3. <div class="detailHeader">
  4. <div>
  5. <div>
  6. <h2>
  7. {{ projectDetail?.['xmmc'] ?? '' }}
  8. <span class="subTitle" v-show="projectDetail?.['xmbh']"
  9. >({{ projectDetail?.['xmbh'] ?? '' }})</span
  10. >
  11. <span class="statu" v-if="projectDetail?.['xmzt'] === 0">立项申请中</span>
  12. <span class="statu" v-else-if="projectDetail?.['xmzt'] === 1">进行中</span>
  13. <span class="statu" v-else-if="projectDetail?.['xmzt'] === 2">已结项</span>
  14. <span class="statu" v-else-if="projectDetail?.['xmzt'] === 3">中止</span>
  15. <span class="statu" v-else-if="projectDetail?.['xmzt'] === 4">已验收</span>
  16. </h2>
  17. </div>
  18. <ul>
  19. <li
  20. v-if="projectPermis.projectPermisState.all || projectPermis.projectPermisState.xmLeader"
  21. v-show="currentIndex === 0"
  22. @click="editorProject"
  23. >{{ !isEditorProject ? '编辑' : '保存' }}
  24. </li>
  25. <template v-if="projectDetail?.['isSign'] === 1">
  26. <template
  27. v-if="
  28. (projectPermis.projectPermisState.all ||
  29. projectPermis.projectPermisState.xsLeader) &&
  30. !signContract.flowStatus &&
  31. isShowSign
  32. "
  33. >
  34. <dialog-confirm
  35. title="是否发起合同签订流程?"
  36. v-if="!signContract?.exist"
  37. @confirm="handleStartContractSign"
  38. >
  39. <template #reference>
  40. <li>合同签订</li>
  41. </template>
  42. </dialog-confirm>
  43. <li
  44. v-else-if="signContract.flowStatus === 1"
  45. @click="processLookHandle(signContract.instanceId)"
  46. >
  47. 合同签订
  48. </li>
  49. </template>
  50. </template>
  51. <li
  52. v-if="projectPermis.projectPermisState.all || projectPermis.projectPermisState.xmLeader"
  53. v-show="currentIndex === 0 && projectDetail?.['xmzt'] !== 3"
  54. @click="addSubProject"
  55. >
  56. 添加子项目
  57. </li>
  58. <li
  59. v-if="
  60. projectPermis.projectPermisState.all ||
  61. projectPermis.projectPermisState.xsLeader ||
  62. projectPermis.projectPermisState.xmLeader
  63. "
  64. v-show="projectDetail?.['xmzt'] !== 3"
  65. @click="handleStartSubcontract"
  66. >
  67. 分包申请
  68. </li>
  69. <li
  70. v-if="
  71. projectPermis.projectPermisState.all ||
  72. projectPermis.projectPermisState.xsLeader ||
  73. projectPermis.projectPermisState.xmLeader
  74. "
  75. v-show="projectDetail?.['xmzt'] !== 3"
  76. @click="handleStartOutsourcing"
  77. >
  78. 外包申请
  79. </li>
  80. <li
  81. v-if="projectPermis.projectPermisState.all || projectPermis.projectPermisState.xmLeader"
  82. v-show="projectDetail?.['xmzt'] === 1"
  83. @click="projectStatusAndProcessHandler('ys')"
  84. >
  85. 验收
  86. </li>
  87. <dialog-confirm
  88. :title="`是否中止项目【${projectDetail?.['xmbh']}】?`"
  89. v-if="projectPermis.projectPermisState.all || projectPermis.projectPermisState.xmLeader"
  90. @confirm="projectTerminateHandler"
  91. >
  92. <template #reference>
  93. <li v-show="projectDetail?.['xmzt'] === 1"> 中止 </li>
  94. </template>
  95. </dialog-confirm>
  96. <dialog-confirm
  97. :title="`是否恢复项目【${projectDetail?.['xmbh']}】?`"
  98. width="280px"
  99. v-if="projectPermis.projectPermisState.all || projectPermis.projectPermisState.xmLeader"
  100. @confirm="projectRecoverHandler"
  101. >
  102. <template #reference>
  103. <li v-show="projectDetail?.['xmzt'] === 3"> 恢复中止 </li>
  104. </template>
  105. </dialog-confirm>
  106. <li
  107. v-if="projectPermis.projectPermisState.all || projectPermis.projectPermisState.xmLeader"
  108. v-show="projectDetail?.['xmzt'] === 4"
  109. @click="projectStatusAndProcessHandler('jx')"
  110. >
  111. 结项
  112. </li>
  113. <li @click="processLookHandle(projectDetail.instanceId)">查看流程</li>
  114. </ul>
  115. </div>
  116. <div>
  117. <ul>
  118. <li @click="switchComponent(XmxxComp, 0)" :class="currentIndex === 0 ? 'active' : ''">
  119. <div><i class="icon"></i>项目信息</div>
  120. </li>
  121. <li
  122. v-show="
  123. signContract.exist && signContract.isvalid == 1 && signContract.flowStatus === 90
  124. "
  125. @click="switchComponent(XmhtComp, 1)"
  126. :class="currentIndex === 1 ? 'active' : ''"
  127. >
  128. <div><i class="icon"></i>项目合同</div>
  129. </li>
  130. <li @click="switchComponent(XmcbComp, 2)" :class="currentIndex === 2 ? 'active' : ''">
  131. <div><i class="icon"></i>项目成本</div>
  132. </li>
  133. <li @click="switchComponent(FjclComp, 3)" :class="currentIndex === 3 ? 'active' : ''">
  134. <div><i class="icon"></i>附件材料</div>
  135. </li>
  136. </ul>
  137. <div class="projectInfo">
  138. <template v-if="projectDetail?.['isSign'] === 0">
  139. <p style="margin-right: 0">该项目不签合同</p>
  140. </template>
  141. <template v-else-if="!signContract.exist">
  142. <p style="margin-right: 0">该项目待签合同</p>
  143. </template>
  144. <template
  145. v-else-if="
  146. signContract.exist && signContract.isvalid == 1 && signContract.flowStatus != 90
  147. "
  148. >
  149. <p style="margin-right: 0">合同签订过程中</p>
  150. </template>
  151. <template v-else>
  152. <p>
  153. <span class="title">合同额(元):</span>
  154. <span class="value">{{ projectDetail?.['contractAmount'] ?? '' }}</span>
  155. </p>
  156. <p>
  157. <span class="title">应收款(元):</span>
  158. <span class="value">{{ projectDetail?.['receivableAmount'] ?? '' }}</span>
  159. </p>
  160. <p>
  161. <span class="title">合同余额(元):</span>
  162. <span class="value">{{ projectDetail?.['contractBalance'] ?? '' }}</span>
  163. </p>
  164. </template>
  165. </div>
  166. </div>
  167. </div>
  168. <div class="detailContent">
  169. <component
  170. :is="currentComponent"
  171. ref="dynamicRef"
  172. :editor="isEditorProject"
  173. :isContract="signContract.exist"
  174. :isEstimateAmount="
  175. signContract.exist &&
  176. signContract.isvalid == 1 &&
  177. (signContract.flowStatus == 90 || signContract.flowStatus == 1)
  178. "
  179. />
  180. </div>
  181. </div>
  182. </template>
  183. <script setup lang="ts">
  184. import { type Component } from 'vue'
  185. import { useRoute } from 'vue-router'
  186. import { useProjectPermis } from '@/store/modules/projectPermis'
  187. import {
  188. isProjectContractExist,
  189. getContractsByProject,
  190. startContractSign,
  191. startOutsourcingApply,
  192. startSubcontractApply
  193. } from '@/service/contract'
  194. import subscribe from '@/utils/Subscribe'
  195. import { openFlow, openProcessFlow } from '@/utils/flow'
  196. import { useMutation } from '@tanstack/vue-query'
  197. import { ProjectId } from '@/interface/project'
  198. import { Contract } from '@/interface/contract'
  199. import {
  200. getProjectWithChildrenById,
  201. projectStatusAndProcess,
  202. projectTerminate,
  203. projectRecover
  204. } from '@/service/project'
  205. import XmxxComp from './components/xmxx/index.vue'
  206. import XmhtComp from './components/xmht/index.vue'
  207. import XmcbComp from './components/xmcb/index.vue'
  208. import FjclComp from './components/fjcl/index.vue'
  209. const router = useRouter()
  210. defineOptions({ name: 'ProjectDetail' })
  211. const message = useMessage()
  212. const dynamicRef = shallowRef<Component>()
  213. const { query } = useRoute()
  214. const { id: projectId, contractId } = query
  215. const currentIndex = ref<number>(0)
  216. const currentComponent = shallowRef<Component>(XmxxComp)
  217. const switchComponent: (c: Component, i: number) => void = (c: Component, i: number) => {
  218. currentComponent.value = c
  219. currentIndex.value = i
  220. }
  221. const projectPermis = useProjectPermis()
  222. projectPermis.initProjectPermis(projectId as string)
  223. /***
  224. * 初始化项目中是否存在合同
  225. */
  226. const signContract = ref<{
  227. exist: boolean //判断是否存在合同
  228. contractId: string
  229. instanceId: string
  230. isvalid: number //判断有没有作废 0 已作废 1 未作废
  231. flowStatus: number //0|null 未开始 1 进行中 90 已完成
  232. }>({
  233. exist: false,
  234. contractId: '',
  235. instanceId: '',
  236. isvalid: 0,
  237. flowStatus: 0
  238. })
  239. const queryProjectContractExist = async (projectId: string) => {
  240. const result: any = await isProjectContractExist(projectId)
  241. if (result) {
  242. signContract.value = result
  243. }
  244. }
  245. queryProjectContractExist(query?.id as string)
  246. /***
  247. * 查询项目详情
  248. * **/
  249. const projectDetail = ref()
  250. const queryProjectByDetail = async (projectId: string) => {
  251. const result = await getProjectWithChildrenById(projectId)
  252. if (result) {
  253. projectDetail.value = result
  254. }
  255. }
  256. queryProjectByDetail(query?.id as string)
  257. subscribe.on('mainContractRefetch', () => {
  258. queryProjectByDetail(query?.id as string)
  259. })
  260. /**
  261. * 添加子项目
  262. * **/
  263. const addSubProject: () => void = () => {
  264. dynamicRef.value?.handleAddSubProject()
  265. }
  266. /**
  267. * 项目中止
  268. */
  269. const projectTerminateHandler = async () => {
  270. const id = projectDetail.value.id
  271. if (!id) {
  272. console.error('项目ID不存在!')
  273. return
  274. }
  275. await projectTerminate(id as string)
  276. message.success('中止成功')
  277. queryProjectByDetail(query?.id as string)
  278. }
  279. /**
  280. * 项目恢复
  281. */
  282. const projectRecoverHandler = async () => {
  283. const id = projectDetail.value.id
  284. if (!id) {
  285. console.error('项目ID不存在!')
  286. return
  287. }
  288. await projectRecover(id as string)
  289. message.success('中止成功')
  290. queryProjectByDetail(query?.id as string)
  291. }
  292. /**
  293. * 发起项目验收或结项
  294. */
  295. const sfysType: Ref<string> = ref('')
  296. const { mutate: startProjectStatusAndProcess } = useMutation(projectStatusAndProcess, {
  297. onSuccess: (data) => {
  298. const subTitle: string =
  299. sfysType.value === 'ys'
  300. ? '验收'
  301. : sfysType.value === 'jx'
  302. ? '结项'
  303. : sfysType.value === 'zz'
  304. ? '中止'
  305. : ''
  306. openFlow(router, data, `项目${subTitle}`)
  307. }
  308. })
  309. const projectStatusAndProcessHandler = (sfys: string) => {
  310. if (!sfys) {
  311. console.warn('sfys字段值不能为空!')
  312. return
  313. }
  314. sfysType.value = sfys
  315. startProjectStatusAndProcess({
  316. projectId: projectId as ProjectId,
  317. sfys
  318. })
  319. }
  320. /**
  321. * 流程查看
  322. */
  323. const processLookHandle = (instanceId: string) => {
  324. openProcessFlow(router, instanceId)
  325. }
  326. /***
  327. * 查询合同数据:存在多主合同情况
  328. * **/
  329. const contractDatas = ref<Contract[]>([])
  330. const queryContractsByProject = async (projectId: string) => {
  331. const tData: Contract[] = await getContractsByProject(projectId)
  332. contractDatas.value = tData
  333. if (contractDatas.value.length > 0 && contractId) {
  334. switchComponent(XmhtComp, 1)
  335. }
  336. }
  337. queryContractsByProject(query?.id as string)
  338. /**
  339. * 项目编辑
  340. * **/
  341. const isEditorProject = ref<boolean>(false)
  342. const editorProject: () => void = (): void => {
  343. isEditorProject.value = !isEditorProject.value
  344. if (isEditorProject.value) return
  345. //@ts-ignore
  346. dynamicRef.value.saveProjectHandle(0)
  347. }
  348. /**
  349. * 发起合同签订
  350. */
  351. const isShowSign = ref<boolean>(true)
  352. const { mutate: startContractSignMutate } = useMutation(startContractSign, {
  353. onSuccess: (data) => openFlow(router, data, '合同签订')
  354. })
  355. const handleStartContractSign = () => {
  356. isShowSign.value = false
  357. startContractSignMutate(projectId as ProjectId)
  358. }
  359. /**
  360. * 发起分包合同申请
  361. */
  362. const { mutate: startSubcontractMutate } = useMutation(startSubcontractApply, {
  363. onSuccess: (data) => openFlow(router, data, '分包申请')
  364. })
  365. const handleStartSubcontract = () => {
  366. startSubcontractMutate(projectDetail.value.id as ProjectId)
  367. }
  368. /**
  369. * 发起外包合同申请
  370. */
  371. const { mutate: startOutsourcingMutate } = useMutation(startOutsourcingApply, {
  372. onSuccess: (data) => openFlow(router, data, '外包申请')
  373. })
  374. const handleStartOutsourcing = () => startOutsourcingMutate(projectDetail.value.id as ProjectId)
  375. </script>
  376. <style lang="scss" scoped>
  377. @import url('./projectDetail.scss');
  378. </style>