ZN
3 天以前 fa113c192df7e3b5aad9dcb465307dcffb58f6c5
src/views/projectManagement/Management/index.vue
@@ -35,10 +35,10 @@
            </el-dropdown-menu>
          </template>
        </el-dropdown> -->
        <el-button @click="handleSubmit">提交</el-button>
        <el-button @click="handleAudit">审核</el-button>
        <el-button @click="handleReverseAudit">反审核</el-button>
        <el-button @click="handleDelete">删除</el-button>
        <el-button :loading="submitLoading" @click="handleSubmit">提交</el-button>
        <el-button :loading="auditLoading" @click="handleAudit">审核</el-button>
        <el-button :loading="reverseAuditLoading" @click="handleReverseAudit">反审核</el-button>
        <el-button :loading="deleteLoading" @click="handleDelete">删除</el-button>
      </div>
      <PIMTable
@@ -58,38 +58,63 @@
        </template>
        <template #action="{ row }">
          <el-button link type="primary" @click="handleEdit(row)">编辑</el-button>
          <el-button link type="primary" @click="handleProgressReport(row)">进度汇报</el-button>
          <el-button link type="primary" @click="handleDiscussProgress(row)">洽谈进展</el-button>
          <el-button link type="primary" :loading="progressBtnLoadingId===row.id" @click="handleProgressReport(row)">进度汇报</el-button>
          <el-button link type="primary" @click="handleDetail(row)">详情</el-button>
        </template>
      </PIMTable>
    </div>
    <FormDia ref="formDiaRef" @completed="getList" />
    <ProgressReportDialog
      v-model="progressReportVisible"
      :project-id="progressProjectId"
      :project-info="progressProjectInfo"
      :plan-nodes="progressPlanNodes"
      :default-plan-node-id="progressDefaultPlanNodeId"
      @submitted="handleProgressSubmitted"
    />
  </div>
</template>
<script setup name="ProjectManagement">
import { ref, reactive, toRefs, onMounted, getCurrentInstance } from 'vue'
import { useRouter } from 'vue-router'
import SearchPanel from '@/components/SearchPanel/index.vue'
import PIMTable from '@/components/PIMTable/PIMTable.vue'
import FormDia from './components/formDia.vue'
import ProgressReportDialog from '@/components/ProjectManagement/ProgressReportDialog.vue'
import {
  listProject,
  delProject,
  submitProject,
  auditProject,
  reverseAuditProject
  reverseAuditProject,
  getProject,
  saveStage
} from '@/api/projectManagement/project'
import { listPlan } from '@/api/projectManagement/projectType'
import { ElMessage, ElMessageBox } from 'element-plus'
import useUserStore from '@/store/modules/user'
const { proxy } = getCurrentInstance()
const { bill_status, project_management, plan_status } = proxy.useDict('bill_status', 'project_management', 'plan_status')
const router = useRouter()
const userStore = useUserStore()
const loading = ref(false)
const ids = ref([])
const tableData = ref([])
const formDiaRef = ref()
const progressReportVisible = ref(false)
const progressProjectId = ref(undefined)
const progressProjectInfo = ref({})
const progressPlanNodes = ref([])
const progressDefaultPlanNodeId = ref(undefined)
const progressBtnLoadingId = ref(null)
const submitLoading = ref(false)
const auditLoading = ref(false)
const reverseAuditLoading = ref(false)
const deleteLoading = ref(false)
const data = reactive({
  queryParams: {
@@ -208,102 +233,174 @@
  formDiaRef.value?.openDialog({ operationType: 'add' })
}
function handleDelete() {
async function handleDelete() {
  const delIds = ids.value
  if (delIds.length === 0) {
    ElMessage.warning('请选择要删除的数据项')
    return
  }
  ElMessageBox.confirm('是否确认删除所选数据项?', '警告', {
  try {
    await ElMessageBox.confirm('是否确认删除所选数据项?', '警告', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  })
    .then(() => delProject(delIds))
    .then(() => {
    deleteLoading.value = true
    await delProject(delIds)
      getList()
      ElMessage.success('删除成功')
    })
    .catch(() => {})
  } catch {} finally {
    deleteLoading.value = false
  }
}
function handleSubmit() {
async function handleSubmit() {
  const submitIds = ids.value
  if (submitIds.length === 0) {
    ElMessage.warning('请选择要提交的数据项')
    return
  }
  ElMessageBox.confirm('是否确认提交所选数据项?', '提示', {
  try {
    await ElMessageBox.confirm('是否确认提交所选数据项?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  })
    .then(async () => {
    submitLoading.value = true
      await Promise.all(submitIds.map(id => submitProject({ id })))
    })
    .then(() => {
      getList()
      ElMessage.success('提交成功')
    })
    .catch(() => {})
  } catch {} finally {
    submitLoading.value = false
  }
}
function handleAudit() {
async function handleAudit() {
  const auditIds = ids.value
  if (auditIds.length === 0) {
    ElMessage.warning('请选择要审核的数据项')
    return
  }
  ElMessageBox.confirm('是否确认审核所选数据项?', '提示', {
  try {
    await ElMessageBox.confirm('是否确认审核所选数据项?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  })
    .then(async () => {
    auditLoading.value = true
      await Promise.all(auditIds.map(id => auditProject({ id })))
    })
    .then(() => {
      getList()
      ElMessage.success('审核成功')
    })
    .catch(() => {})
  } catch {} finally {
    auditLoading.value = false
  }
}
function handleReverseAudit() {
async function handleReverseAudit() {
  const reverseAuditIds = ids.value
  if (reverseAuditIds.length === 0) {
    ElMessage.warning('请选择要反审核的数据项')
    return
  }
  ElMessageBox.confirm('是否确认反审核所选数据项?', '提示', {
  try {
    await ElMessageBox.confirm('是否确认反审核所选数据项?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  })
    .then(async () => {
    reverseAuditLoading.value = true
      await Promise.all(reverseAuditIds.map(id => reverseAuditProject({ id })))
    })
    .then(() => {
      getList()
      ElMessage.success('反审核成功')
    })
    .catch(() => {})
  } catch {} finally {
    reverseAuditLoading.value = false
  }
}
function handleGenerateBill(command) {
  ElMessage.info(`生成单据: ${command}`)
}
function handleProgressReport(row) {
  formDiaRef.value?.openDialog({ operationType: 'view', row })
function computeDefaultPlanNodeId(stageVal, nodes) {
  const list = Array.isArray(nodes) ? nodes : []
  if (list.length === 0) return undefined
  const direct = list.find(n => String(n.id) === String(stageVal))
  if (direct?.id) return direct.id
  const sorted = [...list].sort((a, b) => Number(a.sort ?? 0) - Number(b.sort ?? 0))
  const idx = Number(stageVal)
  if (Number.isFinite(idx)) {
    const byIndex = sorted[idx - 1] || sorted[idx] || sorted[0]
    if (byIndex?.id) return byIndex.id
  }
  return sorted[0]?.id
}
function handleDiscussProgress(row) {
  formDiaRef.value?.openDialog({ operationType: 'view', row })
async function handleProgressReport(row) {
  if (!row?.id) return
  try {
    progressBtnLoadingId.value = row.id
    const res = await getProject(row.id)
    const detail = res?.data?.data ?? res?.data ?? res
    const info = detail?.info || {}
    progressProjectId.value = info.id
    progressProjectInfo.value = info
    const planId = info.projectManagementPlanId
    if (planId) {
      const planRes = await listPlan({ current: 1, size: 999 })
      const records = planRes?.data?.records || planRes?.records || planRes?.rows || []
      const plan = (records || []).find(p => String(p.id) === String(planId)) || {}
      progressPlanNodes.value = Array.isArray(plan?.planNodeList) ? plan.planNodeList : []
    } else {
      progressPlanNodes.value = []
    }
    progressDefaultPlanNodeId.value = computeDefaultPlanNodeId(info.stage, progressPlanNodes.value)
    progressReportVisible.value = true
  } catch (e) {
    ElMessage.error('获取项目详情失败')
  } finally {
    progressBtnLoadingId.value = null
  }
}
async function handleProgressSubmitted(payload) {
  try {
    const nodes = Array.isArray(progressPlanNodes.value) ? progressPlanNodes.value : []
    const node = nodes.find(n => String(n.id) === String(payload.planNodeId)) || {}
    const description = payload.remark
      ? `${payload.reportDate || ''} ${payload.remark}`.trim()
      : `${payload.reportDate || ''} 进度汇报`.trim()
    const req = {
      id: null,
      projectManagementPlanNodeId: payload.planNodeId,
      projectManagementInfoId: progressProjectId.value,
      description,
      actualLeaderId: userStore.id || progressProjectInfo.value?.managerId,
      actualLeaderName: userStore.nickName || progressProjectInfo.value?.managerName,
      estimatedDuration: Number(node.estimatedDuration ?? 0) || 0,
      planStartTime: payload.planStartTime || progressProjectInfo.value?.planStartTime,
      planEndTime: payload.planEndTime || progressProjectInfo.value?.planEndTime,
      actualStartTime: payload.actualStartTime || null,
      actualEndTime: payload.actualEndTime || null,
      progress: Number(payload.totalProgress ?? payload.completionProgress ?? 0) || 0,
      attachmentIds: Array.isArray(payload.attachmentIds) ? payload.attachmentIds : []
    }
    const res = await saveStage(req)
    if (res?.code === 200) {
      ElMessage.success('提交成功')
      getList()
      return
    }
    ElMessage.error(res?.msg || '提交失败')
  } catch (e) {
    ElMessage.error('提交失败')
  }
}
function handleDetail(row) {
  formDiaRef.value?.openDialog({ operationType: 'view', row })
  if (!row?.id) return
  router.push(`/projectManagement/Management/detail/${row.id}`)
}
function handleEdit(row) {