spring
2026-07-03 2540d86f0dbd77f654f558c3bf9d5ddbe7422f16
src/views/mes/pd/project/detail/index.vue
@@ -9,22 +9,24 @@
import { useTabs } from '#/packages/effects/hooks/src';
import { MesPdProjectStatusEnum } from '#/packages/constants/src';
import { Card, Tabs } from 'ant-design-vue';
import { Card, message, Tabs } from 'ant-design-vue';
import {
  archivePdProject,
  auditPdProject,
  getPdProject,
  publishPdProject,
  uploadPdProject,
} from '#/api/mes/pd/project';
import { useDescription } from '#/components/description';
import { ACTION_ICON, TableAction } from '#/adapter/vxe-table';
import { $t } from '#/locales';
import Form from '../modules/form.vue';
import PublishForm from '../modules/publish-form.vue';
import WorkflowActionForm from '../modules/workflow-action-form.vue';
import ReviewList from '../modules/drawing-review/review-list.vue';
import MaterialPanel from '../modules/material-panel.vue';
import TaskDraftBanner from '../modules/task-draft-banner.vue';
import DocumentAuditList from '../modules/document-audit-list.vue';
import DocumentList from '../modules/document-list.vue';
import WorkflowTimeline from '../modules/workflow-timeline.vue';
import TaskDraftBanner from '../modules/task-draft-banner.vue';
import { useDetailSchema } from './data';
const route = useRoute();
@@ -35,37 +37,29 @@
const projectId = ref(0);
const project = ref<MesPdProjectApi.Project>({});
const activeTab = ref('workflow');
const workflowKey = ref(0);
const isDraft = computed(
  () => project.value.status === MesPdProjectStatusEnum.DRAFT,
const isPendingPublish = computed(
  () => project.value.status === MesPdProjectStatusEnum.PENDING_PUBLISH,
);
const isDesigning = computed(
  () => project.value.status === MesPdProjectStatusEnum.DESIGNING,
const isPendingUpload = computed(
  () => project.value.status === MesPdProjectStatusEnum.PENDING_UPLOAD,
);
const isReviewing = computed(
  () => project.value.status === MesPdProjectStatusEnum.REVIEWING,
const isPendingAudit = computed(
  () => project.value.status === MesPdProjectStatusEnum.PENDING_AUDIT,
);
const isApproved = computed(
  () => project.value.status === MesPdProjectStatusEnum.APPROVED,
const isPendingArchive = computed(
  () => project.value.status === MesPdProjectStatusEnum.PENDING_ARCHIVE,
);
const isArchived = computed(
  () => project.value.status === MesPdProjectStatusEnum.ARCHIVED,
);
const isFormEditable = computed(
  () =>
    !isArchived.value &&
    project.value.status !== MesPdProjectStatusEnum.CANCELLED &&
    (isDraft.value || isDesigning.value),
  () => isPendingPublish.value,
);
const materialFormType = computed<FormType>(() =>
  isDesigning.value ? 'update' : 'detail',
);
const showReviewTab = computed(
  () => isReviewing.value || isApproved.value || isArchived.value,
  isPendingPublish.value || isPendingUpload.value || isPendingAudit.value ? 'update' : 'detail',
);
const [Descriptions] = useDescription({
@@ -79,25 +73,14 @@
  destroyOnClose: true,
});
const [PublishModal, publishModalApi] = useVbenModal({
  connectedComponent: PublishForm,
  destroyOnClose: true,
});
const [WorkflowActionModal, workflowActionModalApi] = useVbenModal({
  connectedComponent: WorkflowActionForm,
  destroyOnClose: true,
});
async function loadProjectDetail() {
  loading.value = true;
  try {
    project.value = await getPdProject(projectId.value);
    workflowKey.value += 1;
    if (isDesigning.value) {
    if (isPendingUpload.value) {
      activeTab.value = 'material';
    } else if (isReviewing.value) {
      activeTab.value = 'review';
    } else if (isPendingAudit.value) {
      activeTab.value = 'audit';
    }
  } finally {
    loading.value = false;
@@ -113,12 +96,50 @@
  formModalApi.setData({ formType: 'update', id: projectId.value }).open();
}
function handlePublish() {
  publishModalApi.setData({ id: projectId.value }).open();
async function handlePublish() {
  const hideLoading = message.loading({ content: '发布中…', duration: 0 });
  try {
    await publishPdProject(projectId.value);
    message.success('任务已发布,进入待上传状态');
    loadProjectDetail();
  } finally {
    hideLoading();
  }
}
function handleWorkflowAction(action: 'approve' | 'archive' | 'submit-review') {
  workflowActionModalApi.setData({ id: projectId.value, action }).open();
async function handleUpload() {
  const hideLoading = message.loading({ content: '提交审核中…', duration: 0 });
  try {
    await uploadPdProject(projectId.value);
    message.success('已提交资料审核');
    tabs.closeCurrentTab();
    router.back();
  } finally {
    hideLoading();
  }
}
async function handleAudit() {
  const hideLoading = message.loading({ content: '审核中…', duration: 0 });
  try {
    await auditPdProject(projectId.value);
    message.success('审核通过,进入待归档状态');
    tabs.closeCurrentTab();
    router.back();
  } finally {
    hideLoading();
  }
}
async function handleArchive() {
  const hideLoading = message.loading({ content: '归档中…', duration: 0 });
  try {
    await archivePdProject(projectId.value);
    message.success('已归档');
    loadProjectDetail();
  } finally {
    hideLoading();
  }
}
onMounted(() => {
@@ -131,11 +152,9 @@
  <Page
    auto-content-height
    :loading="loading"
    :title="project.name || '设计任务详情'"
    :title="project.taskName || '设计任务详情'"
  >
    <FormModal @success="loadProjectDetail" />
    <PublishModal @success="loadProjectDetail" />
    <WorkflowActionModal @success="loadProjectDetail" />
    <template #extra>
      <TableAction
@@ -155,40 +174,40 @@
            onClick: handleEdit,
          },
          {
            label: '发布任务',
            label: '发布',
            type: 'primary',
            auth: ['mes:pd-project:update'],
            ifShow: isDraft,
            ifShow: isPendingPublish,
            onClick: handlePublish,
          },
          {
            label: '提交审核',
            type: 'default',
            auth: ['mes:pd-project:submit-review'],
            ifShow: isDesigning,
            onClick: () => handleWorkflowAction('submit-review'),
            label: '确认上传',
            type: 'primary',
            auth: ['mes:pd-project:update'],
            ifShow: isPendingUpload,
            onClick: handleUpload,
          },
          {
            label: '审核通过',
            type: 'primary',
            auth: ['mes:pd-drawing-review:review'],
            ifShow: isReviewing,
            onClick: () => handleWorkflowAction('approve'),
            auth: ['mes:pd-project:audit'],
            ifShow: isPendingAudit,
            onClick: handleAudit,
          },
          {
            label: '归档',
            type: 'default',
            auth: ['mes:pd-project:archive'],
            ifShow: isApproved,
            onClick: () => handleWorkflowAction('archive'),
            ifShow: isPendingArchive,
            onClick: handleArchive,
          },
        ]"
      />
    </template>
    <TaskDraftBanner
      v-if="isDraft"
      :designer-name="project.designerName"
      v-if="isPendingPublish"
      :designer-name="project.chiefDesignerNickname"
      :product-name="project.productName"
      :version="project.version"
      @edit="handleEdit"
@@ -202,21 +221,20 @@
    <Card class="mt-4 min-h-[60%]">
      <Tabs v-model:active-key="activeTab">
        <Tabs.TabPane key="workflow" tab="流程进度" :force-render="true">
          <WorkflowTimeline :key="workflowKey" :project-id="projectId" />
          <WorkflowTimeline :status="project.status ?? 0" />
        </Tabs.TabPane>
        <Tabs.TabPane key="material" tab="设计资料" :force-render="true">
          <p v-if="isDraft" class="mb-3 text-sm text-amber-600">
        <Tabs.TabPane v-if="!isPendingAudit" key="material" tab="设计资料" :force-render="true">
          <p v-if="isPendingPublish" class="mb-3 text-sm text-amber-600">
            请先发布任务后再上传设计资料
          </p>
          <MaterialPanel :form-type="materialFormType" :project-id="projectId" />
          <DocumentList
            :form-type="materialFormType"
            :project-id="projectId"
            :project-status="project.status"
          />
        </Tabs.TabPane>
        <Tabs.TabPane
          v-if="showReviewTab"
          key="review"
          tab="资料审核"
          :force-render="true"
        >
          <ReviewList form-type="detail" :project-id="projectId" />
        <Tabs.TabPane v-if="isPendingAudit" key="audit" tab="资料审核" :force-render="true">
          <DocumentAuditList :project-id="projectId" @success="loadProjectDetail" />
        </Tabs.TabPane>
      </Tabs>
    </Card>