add 项目详细页
parent
cc0e165e7a
commit
3543bce085
|
|
@ -600,6 +600,17 @@ const remainingRouter: AppRouteRecordRaw[] = [
|
|||
},
|
||||
component: () => import('@/views/crm/stationsite/detail/index.vue')
|
||||
},
|
||||
{
|
||||
path: 'project/detail/:id',
|
||||
name: 'CrmProjectDetail',
|
||||
meta: {
|
||||
title: '项目详情',
|
||||
noCache: true,
|
||||
hidden: true,
|
||||
activeMenu: '/crm/project'
|
||||
},
|
||||
component: () => import('@/views/crm/project/detail/index.vue')
|
||||
},
|
||||
{
|
||||
path: 'project/settlement/:id',
|
||||
name: 'CrmProjectSettlementDetail',
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
<template>
|
||||
<ContentWrap>
|
||||
<el-descriptions :column="2">
|
||||
<el-descriptions-item label="同意建桩证明">
|
||||
<div v-if="project.buildPermit">
|
||||
<el-link type="primary" :href="project.buildPermit" target="_blank">查看文件</el-link>
|
||||
</div>
|
||||
<span v-else>-</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="场地权属证明">
|
||||
<div v-if="project.ownershipProof">
|
||||
<el-link type="primary" :href="project.ownershipProof" target="_blank">查看文件</el-link>
|
||||
</div>
|
||||
<span v-else>-</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="项目备案">
|
||||
<div v-if="project.projectRecord">
|
||||
<el-link type="primary" :href="project.projectRecord" target="_blank">查看文件</el-link>
|
||||
</div>
|
||||
<span v-else>-</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="其他补充材料">
|
||||
<div v-if="supplementaryMaterials.length">
|
||||
<div v-for="(file, index) in supplementaryMaterials" :key="index">
|
||||
<el-link type="primary" :href="file" target="_blank">文件{{ index + 1 }}</el-link>
|
||||
</div>
|
||||
</div>
|
||||
<span v-else>-</span>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</ContentWrap>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ProjectVO } from '@/api/crm/project'
|
||||
|
||||
const props = defineProps<{
|
||||
project: ProjectVO
|
||||
}>()
|
||||
|
||||
const supplementaryMaterials = computed(() => {
|
||||
if (!props.project.supplementaryMaterials) return []
|
||||
if (Array.isArray(props.project.supplementaryMaterials)) return props.project.supplementaryMaterials
|
||||
return (props.project.supplementaryMaterials as string).split(',')
|
||||
})
|
||||
</script>
|
||||
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
<template>
|
||||
<ContentWrap>
|
||||
<el-table v-loading="loading" :data="contractList" :stripe="true" :show-overflow-tooltip="true">
|
||||
<el-table-column label="合同类型" fixed="left" align="center" width="120">
|
||||
<template #default="scope">
|
||||
{{ scope.row.contractTypeName }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="合同名称" align="center" prop="name" min-width="200">
|
||||
<template #default="scope">
|
||||
<el-link v-if="scope.row.id" type="primary" :underline="false" @click="openDetail(scope.row.id)">
|
||||
{{ scope.row.name || '-' }}
|
||||
</el-link>
|
||||
<span v-else>{{ scope.row.name || '-' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="合同编号" align="center" prop="no" width="150" />
|
||||
<el-table-column
|
||||
label="合同金额(元)"
|
||||
align="center"
|
||||
prop="totalPrice"
|
||||
width="150"
|
||||
:formatter="erpPriceTableColumnFormatter"
|
||||
/>
|
||||
<el-table-column
|
||||
label="开始时间"
|
||||
align="center"
|
||||
prop="startTime"
|
||||
:formatter="dateFormatter"
|
||||
width="180px"
|
||||
/>
|
||||
<el-table-column
|
||||
label="结束时间"
|
||||
align="center"
|
||||
prop="endTime"
|
||||
:formatter="dateFormatter"
|
||||
width="180px"
|
||||
/>
|
||||
<el-table-column align="center" label="状态" prop="auditStatus" width="100">
|
||||
<template #default="scope">
|
||||
<dict-tag v-if="scope.row.auditStatus !== undefined" :type="DICT_TYPE.CRM_AUDIT_STATUS" :value="scope.row.auditStatus" />
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" fixed="right" label="操作" width="120">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
v-if="scope.row.id"
|
||||
v-hasPermi="['crm:contract:update']"
|
||||
link
|
||||
type="primary"
|
||||
@click="openForm('update', scope.row.id)"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 合作投资协议(如果是合作投资项目) -->
|
||||
<div v-if="project.type === 2 && project.investmentAgreement" class="mt-20px">
|
||||
<el-divider>合作投资协议</el-divider>
|
||||
<el-link type="primary" :href="project.investmentAgreement" target="_blank">查看文件</el-link>
|
||||
</div>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 表单弹窗:编辑 -->
|
||||
<ContractForm ref="formRef" @success="loadContracts" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ProjectVO } from '@/api/crm/project'
|
||||
import * as ContractApi from '@/api/crm/contract'
|
||||
import ContractForm from '@/views/crm/contract/ContractForm.vue'
|
||||
import { dateFormatter } from '@/utils/formatTime'
|
||||
import { DICT_TYPE } from '@/utils/dict'
|
||||
import { erpPriceTableColumnFormatter } from '@/utils'
|
||||
|
||||
const props = defineProps<{
|
||||
project: ProjectVO
|
||||
}>()
|
||||
|
||||
const loading = ref(false)
|
||||
const contractList = ref<any[]>([])
|
||||
const formRef = ref()
|
||||
|
||||
/** 加载合同信息 */
|
||||
const loadContracts = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const contracts: any[] = []
|
||||
|
||||
// 加载场地合同
|
||||
if (props.project.cooperationAgreement) {
|
||||
try {
|
||||
const contract = await ContractApi.getContract(props.project.cooperationAgreement)
|
||||
contracts.push({
|
||||
...contract,
|
||||
contractTypeName: '场地合同',
|
||||
contractTypeId: 1
|
||||
})
|
||||
} catch (error) {
|
||||
// 如果获取失败,至少显示合同ID和名称
|
||||
contracts.push({
|
||||
id: props.project.cooperationAgreement,
|
||||
name: props.project.cooperationAgreementName || `合同ID: ${props.project.cooperationAgreement}`,
|
||||
contractTypeName: '场地合同',
|
||||
contractTypeId: 1
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 加载EPC合同
|
||||
if (props.project.epcContractId) {
|
||||
try {
|
||||
const contract = await ContractApi.getContract(props.project.epcContractId)
|
||||
contracts.push({
|
||||
...contract,
|
||||
contractTypeName: 'EPC合同',
|
||||
contractTypeId: 2
|
||||
})
|
||||
} catch (error) {
|
||||
contracts.push({
|
||||
id: props.project.epcContractId,
|
||||
name: props.project.epcContractName || `合同ID: ${props.project.epcContractId}`,
|
||||
contractTypeName: 'EPC合同',
|
||||
contractTypeId: 2
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 加载设备合同
|
||||
if (props.project.purchaseContractId) {
|
||||
try {
|
||||
const contract = await ContractApi.getContract(props.project.purchaseContractId)
|
||||
contracts.push({
|
||||
...contract,
|
||||
contractTypeName: '设备合同',
|
||||
contractTypeId: 3
|
||||
})
|
||||
} catch (error) {
|
||||
contracts.push({
|
||||
id: props.project.purchaseContractId,
|
||||
name: props.project.purchaseContractName || `合同ID: ${props.project.purchaseContractId}`,
|
||||
contractTypeName: '设备合同',
|
||||
contractTypeId: 3
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
contractList.value = contracts
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 打开合同详情 */
|
||||
const { push } = useRouter()
|
||||
const openDetail = (id: number) => {
|
||||
push({ name: 'CrmContractDetail', params: { id } })
|
||||
}
|
||||
|
||||
/** 打开表单 */
|
||||
const openForm = (type = 'update', id?: number) => {
|
||||
formRef.value?.open(type, id)
|
||||
}
|
||||
|
||||
/** 监听项目变化,重新加载合同 */
|
||||
watch(
|
||||
() => props.project,
|
||||
() => {
|
||||
if (props.project?.id) {
|
||||
loadContracts()
|
||||
}
|
||||
},
|
||||
{ immediate: true, deep: true }
|
||||
)
|
||||
</script>
|
||||
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
<template>
|
||||
<ProjectDetailsHeader :loading="loading" :project="project">
|
||||
<el-button @click="openForm('update', project.id)" type="primary">
|
||||
编辑
|
||||
</el-button>
|
||||
</ProjectDetailsHeader>
|
||||
<el-col>
|
||||
<el-tabs>
|
||||
<el-tab-pane label="合同信息">
|
||||
<ProjectContractInfo :project="project" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="附件">
|
||||
<ProjectAttachmentInfo :project="project" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-col>
|
||||
|
||||
<!-- 表单弹窗:添加/修改 -->
|
||||
<ProjectForm ref="formRef" @success="getProjectData(id)" />
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { useTagsViewStore } from '@/store/modules/tagsView'
|
||||
import * as ProjectApi from '@/api/crm/project'
|
||||
import ProjectDetailsHeader from './projectDetailHeader.vue'
|
||||
import ProjectContractInfo from './ProjectContractInfo.vue'
|
||||
import ProjectAttachmentInfo from './ProjectAttachmentInfo.vue'
|
||||
import ProjectForm from '../ProjectForm.vue'
|
||||
|
||||
defineOptions({ name: 'CrmProjectDetail' })
|
||||
|
||||
const route = useRoute()
|
||||
const message = useMessage()
|
||||
const id = Number(route.params.id) // 编号
|
||||
const loading = ref(true) // 加载中
|
||||
const project = ref<ProjectApi.ProjectVO>({} as ProjectApi.ProjectVO) // 详情
|
||||
|
||||
/** 获取详情 */
|
||||
const getProjectData = async (id: number) => {
|
||||
loading.value = true
|
||||
try {
|
||||
project.value = await ProjectApi.getProject(id)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 编辑 */
|
||||
const formRef = ref()
|
||||
const openForm = (type: string, id?: number) => {
|
||||
formRef.value.open(type, id)
|
||||
}
|
||||
|
||||
/** 初始化 */
|
||||
const { delView } = useTagsViewStore() // 视图操作
|
||||
const { currentRoute } = useRouter() // 路由
|
||||
onMounted(async () => {
|
||||
if (!id) {
|
||||
message.warning('参数错误,项目不能为空!')
|
||||
delView(unref(currentRoute))
|
||||
return
|
||||
}
|
||||
await getProjectData(id)
|
||||
})
|
||||
</script>
|
||||
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
<template>
|
||||
<div>
|
||||
<div class="flex items-start justify-between">
|
||||
<div>
|
||||
<el-col>
|
||||
<el-row>
|
||||
<span class="text-xl font-bold">{{ project.name || '项目详情' }}</span>
|
||||
</el-row>
|
||||
</el-col>
|
||||
</div>
|
||||
<div>
|
||||
<!-- 右上:按钮 -->
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ContentWrap class="mt-10px">
|
||||
<el-descriptions :column="4" direction="horizontal" class="mb-10px">
|
||||
<el-descriptions-item label="场地名称:">
|
||||
{{ siteName }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="项目总投资额:">
|
||||
{{ project.totalInvestment }} 万元
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="状态:">
|
||||
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="project.projectStatus" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="类型:">
|
||||
<dict-tag :type="DICT_TYPE.CRM_PROJECT_TYPE" :value="project.type" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="场地枪数:">
|
||||
{{ project.estimatedPiles }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="部门:">
|
||||
{{ deptName }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="供电类型:">
|
||||
<dict-tag :type="DICT_TYPE.CRM_PROJECT_POWER_SUPPLY_TYPE" :value="project.powerSupplyType" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="供电答复单:" v-if="project.powerSupplyType === 2">
|
||||
<div v-if="project.powerSupplyReply">
|
||||
<el-link type="primary" :href="project.powerSupplyReply" target="_blank">查看文件</el-link>
|
||||
</div>
|
||||
<span v-else>-</span>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<div v-if="project.type === 2 && project.partners && project.partners.length" class="mt-20px">
|
||||
<el-divider>合伙人明细</el-divider>
|
||||
<el-table :data="project.partners" border style="width: 100%">
|
||||
<el-table-column prop="userId" label="合伙人ID" width="120" />
|
||||
<el-table-column prop="ratio" label="出资比例(%)" />
|
||||
<el-table-column prop="investment" label="出资金额(万元)" />
|
||||
</el-table>
|
||||
</div>
|
||||
</ContentWrap>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import * as ProjectApi from '@/api/crm/project'
|
||||
import * as StationSiteApi from '@/api/crm/stationsite'
|
||||
import * as DeptApi from '@/api/system/dept'
|
||||
import { DICT_TYPE } from '@/utils/dict'
|
||||
|
||||
const props = defineProps<{
|
||||
project: ProjectApi.ProjectVO
|
||||
loading: boolean
|
||||
}>()
|
||||
|
||||
const siteName = ref('')
|
||||
const deptName = ref('')
|
||||
|
||||
watch(
|
||||
() => props.project.siteId,
|
||||
async (siteId) => {
|
||||
if (siteId) {
|
||||
const site = await StationSiteApi.getStationSite(siteId)
|
||||
siteName.value = site.name
|
||||
} else {
|
||||
siteName.value = ''
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
watch(
|
||||
() => props.project.deptId,
|
||||
async (deptId) => {
|
||||
if (deptId) {
|
||||
const dept = await DeptApi.getDept(deptId)
|
||||
deptName.value = dept.name
|
||||
} else {
|
||||
deptName.value = ''
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
</script>
|
||||
|
||||
|
|
@ -75,7 +75,19 @@
|
|||
<!-- 列表 -->
|
||||
<ContentWrap>
|
||||
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
|
||||
<el-table-column align="center" label="项目名称" prop="name" min-width="300"/>
|
||||
<el-table-column align="center" label="项目名称" prop="name" min-width="300">
|
||||
<template #default="{ row }">
|
||||
<el-link
|
||||
v-if="row.id"
|
||||
type="primary"
|
||||
@click="openProjectDetail(row.id)"
|
||||
:underline="false"
|
||||
>
|
||||
{{ row.name }}
|
||||
</el-link>
|
||||
<span v-else>{{ row.name }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="项目总投资额(万元)" align="center" prop="totalInvestment" width="180"/>
|
||||
<el-table-column label="枪数" align="center" prop="estimatedPiles" />
|
||||
|
|
@ -213,6 +225,11 @@ const { push } = useRouter()
|
|||
const openSiteDetail = (id: number) => {
|
||||
push({ name: 'CrmStationSiteDetail', params: { id } })
|
||||
}
|
||||
|
||||
/** 打开项目详情 */
|
||||
const openProjectDetail = (id: number) => {
|
||||
push({ name: 'CrmProjectDetail', params: { id: String(id) } })
|
||||
}
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNo = 1
|
||||
|
|
@ -337,4 +354,4 @@ onMounted(async () => {
|
|||
// 加载部门列表
|
||||
deptList.value = await DeptApi.querySimpleDeptList(3)
|
||||
})
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
Loading…
Reference in New Issue