liding
11 小时以前 2c47996a36a10157cbc0df04806f6137952ba419
fix:生产订单状态更改
已修改1个文件
1782 ■■■■ 文件已修改
src/views/productionManagement/productionOrder/index.vue 1782 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productionOrder/index.vue
@@ -1,142 +1,180 @@
<template>
  <div class="app-container">
    <div class="search_form">
      <el-form :model="searchForm"
               :inline="true">
      <el-form :model="searchForm" :inline="true">
        <el-form-item label="生产订单号:">
          <el-input v-model="searchForm.npsNo"
                    placeholder="请输入"
                    clearable
                    prefix-icon="Search"
                    style="width: 160px;"
                    @change="handleQuery" />
          <el-input
            v-model="searchForm.npsNo"
            placeholder="请输入"
            clearable
            prefix-icon="Search"
            style="width: 160px"
            @change="handleQuery"
          />
        </el-form-item>
        <el-form-item label="产品名称:">
          <el-input v-model="searchForm.productName"
                    placeholder="请输入"
                    clearable
                    prefix-icon="Search"
                    style="width: 160px;"
                    @change="handleQuery" />
          <el-input
            v-model="searchForm.productName"
            placeholder="请输入"
            clearable
            prefix-icon="Search"
            style="width: 160px"
            @change="handleQuery"
          />
        </el-form-item>
        <el-form-item label="规格:">
          <el-input v-model="searchForm.model"
                    placeholder="请输入"
                    clearable
                    prefix-icon="Search"
                    style="width: 160px;"
                    @change="handleQuery" />
          <el-input
            v-model="searchForm.model"
            placeholder="请输入"
            clearable
            prefix-icon="Search"
            style="width: 160px"
            @change="handleQuery"
          />
        </el-form-item>
        <el-form-item label="状态:">
          <el-select v-model="searchForm.status"
                     placeholder="请选择"
                     style="width: 160px;"
                     @change="handleQuery">
            <el-option label="待开始"
                       value="1" />
            <el-option label="进行中"
                       value="2" />
            <el-option label="已完成"
                       value="3" />
            <el-option label="已取消"
                       value="4" />
            <el-option label="已结束"
                       value="5" />
          <el-select
            v-model="searchForm.status"
            placeholder="请选择"
            style="width: 160px"
            @change="handleQuery"
          >
            <el-option label="待开始" value="1" />
            <el-option label="进行中" value="2" />
            <el-option label="已完成" value="3" />
            <!--            <el-option label="已取消"-->
            <!--                       value="4" />-->
            <el-option label="已结束" value="5" />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary"
                     @click="handleQuery">搜索</el-button>
          <el-button type="info"
                     @click="handleReset">重置</el-button>
          <el-button type="primary" @click="handleQuery">搜索</el-button>
          <el-button type="info" @click="handleReset">重置</el-button>
        </el-form-item>
      </el-form>
      <div class="action-buttons">
        <!-- <el-button type="primary"
                   @click="isShowNewModal = true">新增</el-button> -->
        <el-button type="danger"
                   @click="handleDelete">退回</el-button>
        <el-button type="danger" @click="handleDelete">退回</el-button>
        <el-button @click="handleOut">导出</el-button>
      </div>
    </div>
    <div class="table_list">
      <PIMTable rowKey="id"
                :column="tableColumn"
                :tableData="tableData"
                :page="page"
                :tableLoading="tableLoading"
                :row-class-name="tableRowClassName"
                :isSelection="true"
                :selectable="row => !row.endOrder"
                @selection-change="handleSelectionChange"
                @pagination="pagination">
      <PIMTable
        rowKey="id"
        :column="tableColumn"
        :tableData="tableData"
        :page="page"
        :tableLoading="tableLoading"
        :row-class-name="tableRowClassName"
        :isSelection="true"
        :selectable="(row) => !row.endOrder"
        @selection-change="handleSelectionChange"
        @pagination="pagination"
      >
        <template #completionStatus="{ row }">
          <el-progress :percentage="toProgressPercentage(row?.completionStatus)"
                       :color="progressColor(toProgressPercentage(row?.completionStatus))"
                       :status="toProgressPercentage(row?.completionStatus) >= 100 ? 'success' : ''" />
          <el-progress
            :percentage="toProgressPercentage(row?.completionStatus)"
            :color="progressColor(toProgressPercentage(row?.completionStatus))"
            :status="
              toProgressPercentage(row?.completionStatus) >= 100
                ? 'success'
                : ''
            "
          />
        </template>
        <template #processRouteStatus="{ row }">
          <div v-if="row.processRouteStatus && row.processRouteStatus.length"
               class="process-progress-container">
            <div v-for="(item, index) in row.processRouteStatus"
                 :key="index"
                 class="process-step">
          <div
            v-if="row.processRouteStatus && row.processRouteStatus.length"
            class="process-progress-container"
          >
            <div
              v-for="(item, index) in row.processRouteStatus"
              :key="index"
              class="process-step"
            >
              <div class="step-content">
                <div class="step-circle"
                     :class="{ 'is-completed': item.percentage >= 100 }">
                  <span class="step-percentage"
                        :style="{ color: item.percentage >= 70 ? item.percentage >= 100 ? '#67c23a' : '#f56c6c' : '#000' }">{{ item.percentage }}%</span>
                <div
                  class="step-circle"
                  :class="{ 'is-completed': item.percentage >= 100 }"
                >
                  <span
                    class="step-percentage"
                    :style="{
                      color:
                        item.percentage >= 70
                          ? item.percentage >= 100
                            ? '#67c23a'
                            : '#f56c6c'
                          : '#000',
                    }"
                    >{{ item.percentage }}%</span
                  >
                </div>
                <div class="step-name">{{ item.name }}</div>
              </div>
              <div v-if="index < row.processRouteStatus.length - 1"
                   class="step-line"></div>
              <div
                v-if="index < row.processRouteStatus.length - 1"
                class="step-line"
              ></div>
            </div>
          </div>
          <span v-else>-</span>
        </template>
      </PIMTable>
    </div>
    <el-dialog v-model="bindRouteDialogVisible"
               title="绑定工艺路线"
               width="500px">
    <el-dialog
      v-model="bindRouteDialogVisible"
      title="绑定工艺路线"
      width="500px"
    >
      <el-form label-width="90px">
        <el-form-item label="工艺路线">
          <el-select v-model="bindForm.routeId"
                     placeholder="请选择工艺路线"
                     style="width: 100%;"
                     :loading="bindRouteLoading">
            <el-option v-for="item in routeOptions"
                       :key="item.id"
                       :label="`${item.processRouteCode || ''}`"
                       :value="item.id" />
          <el-select
            v-model="bindForm.routeId"
            placeholder="请选择工艺路线"
            style="width: 100%"
            :loading="bindRouteLoading"
          >
            <el-option
              v-for="item in routeOptions"
              :key="item.id"
              :label="`${item.processRouteCode || ''}`"
              :value="item.id"
            />
          </el-select>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary"
                     :loading="bindRouteSaving"
                     @click="handleBindRouteConfirm">确 认</el-button>
          <el-button
            type="primary"
            :loading="bindRouteSaving"
            @click="handleBindRouteConfirm"
            >确 认</el-button
          >
          <el-button @click="bindRouteDialogVisible = false">取 消</el-button>
        </span>
      </template>
    </el-dialog>
    <!-- 来源数据弹窗 -->
    <el-dialog v-model="sourceDataDialogVisible"
               title="来源数据"
               width="1200px">
      <div v-if="sourceRowData"
           class="applyno-summary1">
    <el-dialog
      v-model="sourceDataDialogVisible"
      title="来源数据"
      width="1200px"
    >
      <div v-if="sourceRowData" class="applyno-summary1">
        <div class="summary-item">
          <span class="summary-label">产品名称:</span>
          <span class="summary-value">
            <el-tag type="primary">{{ sourceRowData.productName || '-' }}</el-tag>
            <el-tag type="primary">{{
              sourceRowData.productName || "-"
            }}</el-tag>
          </span>
        </div>
        <div class="summary-item">
          <span class="summary-label">规格:</span>
          <span class="summary-value">{{ sourceRowData.model || '-' }}</span>
          <span class="summary-value">{{ sourceRowData.model || "-" }}</span>
        </div>
        <div class="summary-item">
          <span class="summary-label">订单需求数量:</span>
@@ -145,46 +183,60 @@
      </div>
      <div class="source-table-container">
        <div class="source-data-cards-container">
          <div v-for="(item, index) in sourceTableData"
               :key="index"
               class="source-data-card">
          <div
            v-for="(item, index) in sourceTableData"
            :key="index"
            class="source-data-card"
          >
            <div class="card-body">
              <div class="info-grid">
                <div class="info-item">
                  <div class="info-label">计划号</div>
                  <div class="info-value">{{ item.mpsNo || '-' }}</div>
                  <div class="info-value">{{ item.mpsNo || "-" }}</div>
                </div>
                <div class="info-item">
                  <div class="info-label">数据来源</div>
                  <div class="info-value">
                    <el-tag :type="item.source === '销售' ? 'primary' : 'warning'">
                      {{ item.source || '未知' }}
                    <el-tag
                      :type="item.source === '销售' ? 'primary' : 'warning'"
                    >
                      {{ item.source || "未知" }}
                    </el-tag>
                  </div>
                </div>
                <div class="info-item">
                  <div class="info-label">合同号</div>
                  <div class="info-value">{{ item.salesContractNo || '-' }}</div>
                  <div class="info-value">
                    {{ item.salesContractNo || "-" }}
                  </div>
                </div>
                <div class="info-item">
                  <div class="info-label">客户名称</div>
                  <div class="info-value">{{ item.customerName || '-' }}</div>
                  <div class="info-value">{{ item.customerName || "-" }}</div>
                </div>
                <div class="info-item">
                  <div class="info-label">项目名称</div>
                  <div class="info-value">{{ item.projectName || '-' }}</div>
                  <div class="info-value">{{ item.projectName || "-" }}</div>
                </div>
                <div class="info-item">
                  <div class="info-label">计划需求数量</div>
                  <div class="info-value">{{ item.qtyRequired || 0 }} {{ item.unit || '' }}</div>
                  <div class="info-value">
                    {{ item.qtyRequired || 0 }} {{ item.unit || "" }}
                  </div>
                </div>
                <div class="info-item">
                  <div class="info-label">单位</div>
                  <div class="info-value">{{ item.unit || '-' }}</div>
                  <div class="info-value">{{ item.unit || "-" }}</div>
                </div>
                <div class="info-item">
                  <div class="info-label">需求日期</div>
                  <div class="info-value">{{ item.requiredDate ? dayjs(item.requiredDate).format('YYYY-MM-DD') : '-' }}</div>
                  <div class="info-value">
                    {{
                      item.requiredDate
                        ? dayjs(item.requiredDate).format("YYYY-MM-DD")
                        : "-"
                    }}
                  </div>
                </div>
              </div>
            </div>
@@ -192,834 +244,844 @@
        </div>
      </div>
    </el-dialog>
    <MaterialLedgerDialog v-model="materialDialogVisible"
                          :order-row="currentMaterialOrder"
                          @saved="getList" />
    <MaterialDetailDialog v-model="materialDetailDialogVisible"
                          :order-row="currentMaterialDetailOrder"
                          @confirmed="getList" />
    <MaterialSupplementDialog v-model="materialSupplementDialogVisible"
                              :order-row="currentMaterialSupplementOrder"
                              @saved="getList" />
    <new-product-order v-if="isShowNewModal"
                       v-model:visible="isShowNewModal"
                       @completed="handleQuery" />
    <MaterialLedgerDialog
      v-model="materialDialogVisible"
      :order-row="currentMaterialOrder"
      @saved="getList"
    />
    <MaterialDetailDialog
      v-model="materialDetailDialogVisible"
      :order-row="currentMaterialDetailOrder"
      @confirmed="getList"
    />
    <MaterialSupplementDialog
      v-model="materialSupplementDialogVisible"
      :order-row="currentMaterialSupplementOrder"
      @saved="getList"
    />
    <new-product-order
      v-if="isShowNewModal"
      v-model:visible="isShowNewModal"
      @completed="handleQuery"
    />
    <!-- 打印领料单组件 -->
    <div class="print-requisition-wrapper">
      <PrintMaterialRequisition ref="printRef"
                                :order-row="printOrderRow"
                                :material-list="printMaterialList" />
      <PrintMaterialRequisition
        ref="printRef"
        :order-row="printOrderRow"
        :material-list="printMaterialList"
      />
    </div>
  </div>
</template>
<script setup>
  import {
    computed,
    defineAsyncComponent,
    getCurrentInstance,
    onMounted,
    reactive,
    ref,
    toRefs,
  } from "vue";
  import { ElMessageBox } from "element-plus";
  import dayjs from "dayjs";
  import { useRouter } from "vue-router";
  import {
    productOrderListPage,
    listProcessRoute,
    bindingRoute,
    listProcessBom,
    delProductOrder,
    getProductOrderSource,
    updateProductOrder,
  } from "@/api/productionManagement/productionOrder.js";
  import { productWorkOrderPage } from "@/api/productionManagement/workOrder.js";
  import { listMain as getOrderProcessRouteMain } from "@/api/productionManagement/productProcessRoute.js";
  import MaterialLedgerDialog from "@/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue";
  import MaterialDetailDialog from "@/views/productionManagement/productionOrder/components/MaterialDetailDialog.vue";
  import MaterialSupplementDialog from "@/views/productionManagement/productionOrder/components/MaterialSupplementDialog.vue";
  import PrintMaterialRequisition from "@/views/productionManagement/productionOrder/components/PrintMaterialRequisition.vue";
  import PIMTable from "@/components/PIMTable/PIMTable.vue";
  import { listPage } from "@/api/productionManagement/processRoute.js";
  import {
    listMaterialPickingDetail,
    listMaterialPickingBom,
  } from "@/api/productionManagement/productionOrder.js";
  const NewProductOrder = defineAsyncComponent(() =>
    import("@/views/productionManagement/productionOrder/New.vue")
import {
  computed,
  defineAsyncComponent,
  getCurrentInstance,
  onMounted,
  reactive,
  ref,
  toRefs,
} from "vue";
import { ElMessageBox } from "element-plus";
import dayjs from "dayjs";
import { useRouter } from "vue-router";
import {
  productOrderListPage,
  listProcessRoute,
  bindingRoute,
  listProcessBom,
  delProductOrder,
  getProductOrderSource,
  updateProductOrder,
} from "@/api/productionManagement/productionOrder.js";
import { productWorkOrderPage } from "@/api/productionManagement/workOrder.js";
import { listMain as getOrderProcessRouteMain } from "@/api/productionManagement/productProcessRoute.js";
import MaterialLedgerDialog from "@/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue";
import MaterialDetailDialog from "@/views/productionManagement/productionOrder/components/MaterialDetailDialog.vue";
import MaterialSupplementDialog from "@/views/productionManagement/productionOrder/components/MaterialSupplementDialog.vue";
import PrintMaterialRequisition from "@/views/productionManagement/productionOrder/components/PrintMaterialRequisition.vue";
import PIMTable from "@/components/PIMTable/PIMTable.vue";
import { listPage } from "@/api/productionManagement/processRoute.js";
import {
  listMaterialPickingDetail,
  listMaterialPickingBom,
} from "@/api/productionManagement/productionOrder.js";
const NewProductOrder = defineAsyncComponent(() =>
  import("@/views/productionManagement/productionOrder/New.vue")
);
const { proxy } = getCurrentInstance();
const router = useRouter();
const isShowNewModal = ref(false);
const sourceDataDialogVisible = ref(false);
const sourceTableData = ref([]);
const sourceRowData = ref(null);
const sourcePage = reactive({
  total: 0,
});
const processColumnWidth = computed(() => {
  if (!tableData.value || tableData.value.length === 0) return "200px";
  const maxProcesses = Math.max(
    ...tableData.value.map((row) => row.processRouteStatus?.length || 0)
  );
  if (maxProcesses === 0) return "100px";
  // 每个工序圆圈 36px + 线条 30px = 66px,额外加 60px 边距和文字空间
  return `${maxProcesses * 66 + 60}px`;
});
  const { proxy } = getCurrentInstance();
const tableColumn = computed(() => [
  {
    label: "生产订单号",
    prop: "npsNo",
    width: "150px",
  },
  // 1.待开始、2.进行中、3.已完成、4.已取消、5.已结束
  {
    label: "状态",
    prop: "status",
    width: "150px",
    dataType: "tag",
    formatData: (val) =>
      val === 1
        ? "待开始"
        : val === 2
        ? "进行中"
        : val === 3
        ? "已完成"
        : val === 5
        ? "已结束"
        : "已取消",
    formatType: (val) =>
      val === 1
        ? "primary"
        : val === 2
        ? "warning"
        : val === 3
        ? "success"
        : val === 5
        ? "danger"
        : "info",
  },
  {
    label: "产品名称",
    prop: "productName",
    width: "120px",
  },
  {
    label: "规格",
    prop: "model",
    width: "120px",
  },
  {
    label: "工艺路线编号",
    prop: "processRouteCode",
    width: "200px",
  },
  {
    label: "需求数量",
    prop: "quantity",
  },
  {
    label: "完成数量",
    prop: "completeQuantity",
  },
  {
    label: "工序生产进度",
    prop: "processRouteStatus",
    dataType: "slot",
    slot: "processRouteStatus",
    width: processColumnWidth.value,
  },
  {
    dataType: "slot",
    label: "完成进度",
    prop: "completionStatus",
    slot: "completionStatus",
    width: 180,
  },
  {
    label: "开始日期",
    prop: "startTime",
    formatData: (val) => (val ? dayjs(val).format("YYYY-MM-DD") : ""),
    width: 120,
  },
  {
    label: "结束日期",
    prop: "endTime",
    formatData: (val) => (val ? dayjs(val).format("YYYY-MM-DD") : ""),
    width: 120,
  },
  {
    label: "计划完成时间",
    prop: "planCompleteTime",
    formatData: (val) => (val ? dayjs(val).format("YYYY-MM-DD") : ""),
    width: 120,
  },
  {
    dataType: "action",
    label: "操作",
    align: "center",
    fixed: "right",
    width: 280,
    operation: [
      {
        name: "工艺路线",
        type: "text",
        showHide: (row) => row.processRouteCode,
        clickFun: (row) => {
          showRouteItemModal(row);
        },
      },
      {
        name: "绑定工艺路线",
        type: "text",
        showHide: (row) => !row.processRouteCode && !row.endOrder,
        clickFun: (row) => {
          openBindRouteDialog(row, "add");
        },
      },
      {
        name: "更换工艺路线",
        type: "text",
        showHide: (row) => row.processRouteCode && !row.endOrder,
        clickFun: (row) => {
          openBindRouteDialog(row, "change");
        },
      },
      {
        name: "来源",
        type: "text",
        clickFun: (row) => {
          showSourceData(row);
        },
      },
      {
        name: "领料",
        type: "text",
        color: "#5EC7AB",
        showHide: (row) => !row.endOrder && !row.returned,
        clickFun: (row) => {
          openMaterialDialog(row);
        },
      },
      {
        name: "补料",
        type: "text",
        color: "#5EC7AB",
        showHide: (row) => !row.endOrder && !row.returned,
        clickFun: (row) => {
          openMaterialSupplementDialog(row);
        },
      },
      {
        name: "领料详情",
        type: "text",
        color: "#5EC7AB",
        clickFun: (row) => {
          openMaterialDetailDialog(row);
        },
      },
      {
        name: "打印领料单",
        type: "text",
        color: "#5EC7AB",
        showHide: (row) => !row.endOrder,
        clickFun: (row) => {
          handlePrint(row);
        },
      },
      {
        name: "生产追溯",
        type: "text",
        color: "#409eff",
        clickFun: (row) => {
          router.push({
            path: "/productionManagement/productionTraceability",
            query: {
              npsNo: row.npsNo,
              productName: row.productName,
              model: row.model,
            },
          });
        },
      },
      {
        name: "结束订单",
        type: "text",
        color: "red",
        showHide: (row) => !row.endOrder,
        clickFun: (row) => {
          handleEndOrder(row);
        },
      },
    ],
  },
]);
const tableData = ref([]);
const tableLoading = ref(false);
const page = reactive({
  current: 1,
  size: 100,
  total: 0,
});
const selectedRows = ref([]);
  const router = useRouter();
  const isShowNewModal = ref(false);
  const sourceDataDialogVisible = ref(false);
  const sourceTableData = ref([]);
  const sourceRowData = ref(null);
  const sourcePage = reactive({
    total: 0,
  });
const data = reactive({
  searchForm: {
    npsNo: "",
    customerName: "",
    salesContractNo: "",
    projectName: "",
    productName: "",
    model: "",
    status: "",
  },
});
const { searchForm } = toRefs(data);
  const processColumnWidth = computed(() => {
    if (!tableData.value || tableData.value.length === 0) return "200px";
    const maxProcesses = Math.max(
      ...tableData.value.map(row => row.processRouteStatus?.length || 0)
    );
    if (maxProcesses === 0) return "100px";
    // 每个工序圆圈 36px + 线条 30px = 66px,额外加 60px 边距和文字空间
    return `${maxProcesses * 66 + 60}px`;
  });
const toProgressPercentage = (val) => {
  const n = Number(val);
  if (!Number.isFinite(n)) return 0;
  if (n <= 0) return 0;
  if (n >= 100) return 100;
  return parseFloat(n.toFixed(2));
};
  const tableColumn = computed(() => [
    {
      label: "生产订单号",
      prop: "npsNo",
      width: "150px",
    },
    // 1.待开始、2.进行中、3.已完成、4.已取消、5.已结束
    {
      label: "状态",
      prop: "status",
      width: "150px",
      dataType: "tag",
      formatData: val =>
        val === 1
          ? "待开始"
          : val === 2
          ? "进行中"
          : val === 3
          ? "已完成"
          : val === 5
          ? "已结束"
          : "已取消",
      formatType: val =>
        val === 1
          ? "primary"
          : val === 2
          ? "warning"
          : val === 3
          ? "success"
          : val === 5
          ? "danger"
          : "info",
    },
    {
      label: "产品名称",
      prop: "productName",
      width: "120px",
    },
    {
      label: "规格",
      prop: "model",
      width: "120px",
    },
    {
      label: "工艺路线编号",
      prop: "processRouteCode",
      width: "200px",
    },
    {
      label: "需求数量",
      prop: "quantity",
    },
    {
      label: "完成数量",
      prop: "completeQuantity",
    },
    {
      label: "工序生产进度",
      prop: "processRouteStatus",
      dataType: "slot",
      slot: "processRouteStatus",
      width: processColumnWidth.value,
    },
    {
      dataType: "slot",
      label: "完成进度",
      prop: "completionStatus",
      slot: "completionStatus",
      width: 180,
    },
    {
      label: "开始日期",
      prop: "startTime",
      formatData: val => (val ? dayjs(val).format("YYYY-MM-DD") : ""),
      width: 120,
    },
    {
      label: "结束日期",
      prop: "endTime",
      formatData: val => (val ? dayjs(val).format("YYYY-MM-DD") : ""),
      width: 120,
    },
    {
      label: "计划完成时间",
      prop: "planCompleteTime",
      formatData: val => (val ? dayjs(val).format("YYYY-MM-DD") : ""),
      width: 120,
    },
    {
      dataType: "action",
      label: "操作",
      align: "center",
      fixed: "right",
      width: 280,
      operation: [
        {
          name: "工艺路线",
          type: "text",
          showHide: row => row.processRouteCode,
          clickFun: row => {
            showRouteItemModal(row);
          },
        },
        {
          name: "绑定工艺路线",
          type: "text",
          showHide: row => !row.processRouteCode && !row.endOrder,
          clickFun: row => {
            openBindRouteDialog(row, "add");
          },
        },
        {
          name: "更换工艺路线",
          type: "text",
          showHide: row => row.processRouteCode && !row.endOrder,
          clickFun: row => {
            openBindRouteDialog(row, "change");
          },
        },
        {
          name: "来源",
          type: "text",
          clickFun: row => {
            showSourceData(row);
          },
        },
        {
          name: "领料",
          type: "text",
          color: "#5EC7AB",
          showHide: row => !row.endOrder && !row.returned,
          clickFun: row => {
            openMaterialDialog(row);
          },
        },
        {
          name: "补料",
          type: "text",
          color: "#5EC7AB",
          showHide: row => !row.endOrder && !row.returned,
          clickFun: row => {
            openMaterialSupplementDialog(row);
          },
        },
        {
          name: "领料详情",
          type: "text",
          color: "#5EC7AB",
          clickFun: row => {
            openMaterialDetailDialog(row);
          },
        },
        {
          name: "打印领料单",
          type: "text",
          color: "#5EC7AB",
          showHide: row => !row.endOrder,
          clickFun: row => {
            handlePrint(row);
          },
        },
        {
          name: "生产追溯",
          type: "text",
          color: "#409eff",
          clickFun: row => {
            router.push({
              path: "/productionManagement/productionTraceability",
              query: {
                npsNo: row.npsNo,
                productName: row.productName,
                model: row.model,
              },
// 30/50/80/100 分段颜色:红/橙/蓝/绿
const progressColor = (percentage) => {
  const p = toProgressPercentage(percentage);
  if (p < 30) return "#f56c6c";
  if (p < 50) return "#e6a23c";
  if (p < 80) return "#409eff";
  return "#67c23a";
};
// 添加表行类名方法
const tableRowClassName = ({ row }) => {
  if (!row.planCompleteTime) return "";
  if (row.isFh) return "";
  const diff = row.deliveryDaysDiff;
  if (diff === 15) {
    return "yellow";
  } else if (diff === 10) {
    return "pink";
  } else if (diff === 2) {
    return "purple";
  } else if (diff < 2) {
    return "red";
  }
};
// 绑定工艺路线弹框
const bindRouteDialogVisible = ref(false);
const bindRouteLoading = ref(false);
const bindRouteSaving = ref(false);
const routeOptions = ref([]);
const bindForm = reactive({
  orderId: null,
  routeId: null,
});
const materialDialogVisible = ref(false);
const currentMaterialOrder = ref(null);
const materialDetailDialogVisible = ref(false);
const currentMaterialDetailOrder = ref(null);
const materialSupplementDialogVisible = ref(false);
const currentMaterialSupplementOrder = ref(null);
// 打印相关
const printOrderRow = ref(null);
const printMaterialList = ref([]);
const handlePrint = async (row) => {
  printOrderRow.value = row;
  proxy.$modal.loading("正在获取领料数据...");
  try {
    printMaterialList.value = [];
    const detailRes = await listMaterialPickingDetail(row.id);
    const detailList = Array.isArray(detailRes?.data)
      ? detailRes.data
      : detailRes?.data?.records || [];
    if (detailList.length > 0) {
      printMaterialList.value = detailList;
    }
    if (printMaterialList.value.length === 0) {
      proxy.$modal.msgWarning("暂无领料数据");
      return;
    }
    // 等待 DOM 更新后执行打印
    proxy.$nextTick(() => {
      setTimeout(() => {
        window.print();
      }, 800);
    });
  } catch (e) {
    console.error("获取领料数据失败:", e);
    proxy.$modal.msgError("获取领料数据失败");
  } finally {
    proxy.$modal.closeLoading();
  }
};
const openBindRouteDialog = async (row, type) => {
  bindForm.orderId = row.id;
  bindForm.routeId = type === "add" ? null : row.technologyRoutingId;
  bindRouteDialogVisible.value = true;
  routeOptions.value = [];
  if (!row.productModelId) {
    proxy.$modal.msgWarning("当前订单缺少产品型号,无法查询工艺路线");
    bindRouteDialogVisible.value = false;
    return;
  }
  bindRouteLoading.value = true;
  try {
    const res = await listPage({ productModelId: row.productModelId });
    routeOptions.value = res.data.records || [];
  } catch (e) {
    console.error("获取工艺路线列表失败:", e);
    proxy.$modal.msgError("获取工艺路线列表失败");
  } finally {
    bindRouteLoading.value = false;
  }
};
const handleBindRouteConfirm = async () => {
  if (!bindForm.routeId) {
    proxy.$modal.msgWarning("请选择工艺路线");
    return;
  }
  bindRouteSaving.value = true;
  try {
    await bindingRoute({
      id: bindForm.orderId,
      technologyRoutingId: bindForm.routeId,
    });
    proxy.$modal.msgSuccess("绑定成功");
    bindRouteDialogVisible.value = false;
    getList();
  } catch (e) {
    console.error("绑定工艺路线失败:", e);
    proxy.$modal.msgError("绑定工艺路线失败");
  } finally {
    bindRouteSaving.value = false;
  }
};
const openMaterialDialog = (row) => {
  currentMaterialOrder.value = row;
  materialDialogVisible.value = true;
};
const openMaterialDetailDialog = async (row) => {
  currentMaterialDetailOrder.value = row;
  materialDetailDialogVisible.value = true;
};
const openMaterialSupplementDialog = (row) => {
  currentMaterialSupplementOrder.value = row;
  materialSupplementDialogVisible.value = true;
};
const handleReset = () => {
  searchForm.value = {
    ...searchForm.value,
    npsNo: "",
    customerName: "",
    salesContractNo: "",
    projectName: "",
    productName: "",
    model: "",
    status: "",
  };
  handleQuery();
};
// 查询列表
/** 搜索按钮操作 */
const handleQuery = () => {
  page.current = 1;
  getList();
};
const pagination = (obj) => {
  page.current = obj.page;
  page.size = obj.limit;
  getList();
};
const changeDaterange = (value) => {
  if (value) {
    searchForm.value.entryDateStart = value[0];
    searchForm.value.entryDateEnd = value[1];
  } else {
    searchForm.value.entryDateStart = undefined;
    searchForm.value.entryDateEnd = undefined;
  }
  handleQuery();
};
const getList = () => {
  tableLoading.value = true;
  // 构造一个新的对象,不包含entryDate字段
  const params = { ...searchForm.value, ...page };
  params.entryDate = undefined;
  productOrderListPage(params)
    .then(async (res) => {
      const records = res.data.records || [];
      // 为每个订单查询对应的工序进度数据
      const processPromises = records.map(async (item) => {
        if (item.npsNo) {
          try {
            const workOrderRes = await productWorkOrderPage({
              npsNo: item.npsNo,
              size: 100,
            });
          },
        },
        {
          name: "结束订单",
          type: "text",
          color: "red",
          showHide: row => !row.endOrder,
          clickFun: row => {
            handleEndOrder(row);
          },
        },
      ],
    },
  ]);
  const tableData = ref([]);
  const tableLoading = ref(false);
  const page = reactive({
    current: 1,
    size: 100,
    total: 0,
  });
  const selectedRows = ref([]);
  const data = reactive({
    searchForm: {
      npsNo: "",
      customerName: "",
      salesContractNo: "",
      projectName: "",
      productName: "",
      model: "",
      status: "",
    },
  });
  const { searchForm } = toRefs(data);
  const toProgressPercentage = val => {
    const n = Number(val);
    if (!Number.isFinite(n)) return 0;
    if (n <= 0) return 0;
    if (n >= 100) return 100;
    return parseFloat(n.toFixed(2));
  };
  // 30/50/80/100 分段颜色:红/橙/蓝/绿
  const progressColor = percentage => {
    const p = toProgressPercentage(percentage);
    if (p < 30) return "#f56c6c";
    if (p < 50) return "#e6a23c";
    if (p < 80) return "#409eff";
    return "#67c23a";
  };
  // 添加表行类名方法
  const tableRowClassName = ({ row }) => {
    if (!row.planCompleteTime) return "";
    if (row.isFh) return "";
    const diff = row.deliveryDaysDiff;
    if (diff === 15) {
      return "yellow";
    } else if (diff === 10) {
      return "pink";
    } else if (diff === 2) {
      return "purple";
    } else if (diff < 2) {
      return "red";
    }
  };
  // 绑定工艺路线弹框
  const bindRouteDialogVisible = ref(false);
  const bindRouteLoading = ref(false);
  const bindRouteSaving = ref(false);
  const routeOptions = ref([]);
  const bindForm = reactive({
    orderId: null,
    routeId: null,
  });
  const materialDialogVisible = ref(false);
  const currentMaterialOrder = ref(null);
  const materialDetailDialogVisible = ref(false);
  const currentMaterialDetailOrder = ref(null);
  const materialSupplementDialogVisible = ref(false);
  const currentMaterialSupplementOrder = ref(null);
  // 打印相关
  const printOrderRow = ref(null);
  const printMaterialList = ref([]);
  const handlePrint = async row => {
    printOrderRow.value = row;
    proxy.$modal.loading("正在获取领料数据...");
    try {
      printMaterialList.value = [];
      const detailRes = await listMaterialPickingDetail(row.id);
      const detailList = Array.isArray(detailRes?.data)
        ? detailRes.data
        : detailRes?.data?.records || [];
      if (detailList.length > 0) {
        printMaterialList.value = detailList;
      }
      if (printMaterialList.value.length === 0) {
        proxy.$modal.msgWarning("暂无领料数据");
        return;
      }
      // 等待 DOM 更新后执行打印
      proxy.$nextTick(() => {
        setTimeout(() => {
          window.print();
        }, 800);
      });
    } catch (e) {
      console.error("获取领料数据失败:", e);
      proxy.$modal.msgError("获取领料数据失败");
    } finally {
      proxy.$modal.closeLoading();
    }
  };
  const openBindRouteDialog = async (row, type) => {
    bindForm.orderId = row.id;
    bindForm.routeId = type === "add" ? null : row.technologyRoutingId;
    bindRouteDialogVisible.value = true;
    routeOptions.value = [];
    if (!row.productModelId) {
      proxy.$modal.msgWarning("当前订单缺少产品型号,无法查询工艺路线");
      bindRouteDialogVisible.value = false;
      return;
    }
    bindRouteLoading.value = true;
    try {
      const res = await listPage({ productModelId: row.productModelId });
      routeOptions.value = res.data.records || [];
    } catch (e) {
      console.error("获取工艺路线列表失败:", e);
      proxy.$modal.msgError("获取工艺路线列表失败");
    } finally {
      bindRouteLoading.value = false;
    }
  };
  const handleBindRouteConfirm = async () => {
    if (!bindForm.routeId) {
      proxy.$modal.msgWarning("请选择工艺路线");
      return;
    }
    bindRouteSaving.value = true;
    try {
      await bindingRoute({
        id: bindForm.orderId,
        technologyRoutingId: bindForm.routeId,
      });
      proxy.$modal.msgSuccess("绑定成功");
      bindRouteDialogVisible.value = false;
      getList();
    } catch (e) {
      console.error("绑定工艺路线失败:", e);
      proxy.$modal.msgError("绑定工艺路线失败");
    } finally {
      bindRouteSaving.value = false;
    }
  };
  const openMaterialDialog = row => {
    currentMaterialOrder.value = row;
    materialDialogVisible.value = true;
  };
  const openMaterialDetailDialog = async row => {
    currentMaterialDetailOrder.value = row;
    materialDetailDialogVisible.value = true;
  };
  const openMaterialSupplementDialog = row => {
    currentMaterialSupplementOrder.value = row;
    materialSupplementDialogVisible.value = true;
  };
  const handleReset = () => {
    searchForm.value = {
      ...searchForm.value,
      npsNo: "",
      customerName: "",
      salesContractNo: "",
      projectName: "",
      productName: "",
      model: "",
      status: "",
    };
    handleQuery();
  };
  // 查询列表
  /** 搜索按钮操作 */
  const handleQuery = () => {
    page.current = 1;
    getList();
  };
  const pagination = obj => {
    page.current = obj.page;
    page.size = obj.limit;
    getList();
  };
  const changeDaterange = value => {
    if (value) {
      searchForm.value.entryDateStart = value[0];
      searchForm.value.entryDateEnd = value[1];
    } else {
      searchForm.value.entryDateStart = undefined;
      searchForm.value.entryDateEnd = undefined;
    }
    handleQuery();
  };
  const getList = () => {
    tableLoading.value = true;
    // 构造一个新的对象,不包含entryDate字段
    const params = { ...searchForm.value, ...page };
    params.entryDate = undefined;
    productOrderListPage(params)
      .then(async res => {
        const records = res.data.records || [];
        // 为每个订单查询对应的工序进度数据
        const processPromises = records.map(async item => {
          if (item.npsNo) {
            try {
              const workOrderRes = await productWorkOrderPage({
                npsNo: item.npsNo,
                size: 100,
              });
              const workOrders = workOrderRes.data.records || [];
              // 按照工序顺序排序(如果有顺序字段,假设为 orderNum 或按返回顺序)
              // 转换为 processRouteStatus 格式
              const processRouteStatus = workOrders.map(wo => ({
                name: wo.operationName || "未知工序",
                percentage: wo.completionStatus > 100 ? 100 : wo.completionStatus,
              }));
              return { ...item, processRouteStatus };
            } catch (error) {
              console.error(`获取工单 ${item.npsNo} 进度失败:`, error);
              return { ...item, processRouteStatus: [] };
            }
            const workOrders = workOrderRes.data.records || [];
            // 按照工序顺序排序(如果有顺序字段,假设为 orderNum 或按返回顺序)
            // 转换为 processRouteStatus 格式
            const processRouteStatus = workOrders.map((wo) => ({
              name: wo.operationName || "未知工序",
              percentage: wo.completionStatus > 100 ? 100 : wo.completionStatus,
            }));
            return { ...item, processRouteStatus };
          } catch (error) {
            console.error(`获取工单 ${item.npsNo} 进度失败:`, error);
            return { ...item, processRouteStatus: [] };
          }
          return { ...item, processRouteStatus: [] };
        });
        tableData.value = await Promise.all(processPromises);
        page.total = res.data.total;
        tableLoading.value = false;
      })
      .catch(() => {
        tableLoading.value = false;
        }
        return { ...item, processRouteStatus: [] };
      });
  };
  const showRouteItemModal = async row => {
    const orderId = row.id;
    try {
      const res = await getOrderProcessRouteMain(orderId);
      const data = res.data || {};
      if (!data || !data.id) {
        proxy.$modal.msgWarning("未找到关联的工艺路线");
        return;
      }
      router.push({
        path: "/productionManagement/processRouteItem",
        query: {
          id: data.id,
          bomId: data.orderBomId,
          processRouteCode: data.processRouteCode || "",
          productName: row.productName || "",
          model: row.model || "",
          bomNo: row.bomNo || "",
          description: data.description || "",
          quantity: row.quantity || 0,
          technologyRoutingId: data.technologyRoutingId,
          orderId,
          type: "order",
          editable: !row.endOrder,
        },
      });
    } catch (e) {
      console.error("获取工艺路线主信息失败:", e);
      proxy.$modal.msgError("获取工艺路线信息失败");
      tableData.value = await Promise.all(processPromises);
      page.total = res.data.total;
      tableLoading.value = false;
    })
    .catch(() => {
      tableLoading.value = false;
    });
};
const showRouteItemModal = async (row) => {
  const orderId = row.id;
  try {
    const res = await getOrderProcessRouteMain(orderId);
    const data = res.data || {};
    if (!data || !data.id) {
      proxy.$modal.msgWarning("未找到关联的工艺路线");
      return;
    }
  };
  const showProductStructure = row => {
    router.push({
      path: "/productionManagement/productStructureDetail",
      path: "/productionManagement/processRouteItem",
      query: {
        id: row.id,
        bomNo: row.bomNo || "",
        id: data.id,
        bomId: data.orderBomId,
        processRouteCode: data.processRouteCode || "",
        productName: row.productName || "",
        productModelName: row.model || "",
        orderId: row.id,
        model: row.model || "",
        bomNo: row.bomNo || "",
        description: data.description || "",
        quantity: row.quantity || 0,
        technologyRoutingId: data.technologyRoutingId,
        orderId,
        type: "order",
        editable: !row.endOrder,
      },
    });
  };
  } catch (e) {
    console.error("获取工艺路线主信息失败:", e);
    proxy.$modal.msgError("获取工艺路线信息失败");
  }
};
  // 查看来源生产计划数据
  const showSourceData = row => {
    // 存储点击来源按钮时传递的row参数
    sourceRowData.value = row;
    // 调用API获取来源数据
    getProductOrderSource(row.id)
      .then(res => {
        if (res.code === 200) {
          // 直接存储返回的扁平化数据
          sourceTableData.value = res.data || [];
          sourcePage.total = sourceTableData.value.length;
          // 打开弹窗
          sourceDataDialogVisible.value = true;
        } else {
          proxy.$modal.msgError(res.msg || "获取来源数据失败");
        }
      })
      .catch(err => {
        proxy.$modal.msgError("获取来源数据失败");
        console.error(err);
      });
  };
  // 表格选择数据
  const handleSelectionChange = selection => {
    selectedRows.value = selection;
  };
  const handleDelete = () => {
    let ids = [];
    if (selectedRows.value.length > 0) {
      ids = selectedRows.value.map(item => item.id);
    } else {
      proxy.$modal.msgWarning("请选择数据");
      return;
    }
    ElMessageBox.confirm("是否退回该生产订单?", "退回", {
      confirmButtonText: "确认",
      cancelButtonText: "取消",
      type: "warning",
    })
      .then(() => {
        console.log(ids, "ids");
        delProductOrder(ids).then(res => {
          proxy.$modal.msgSuccess("退回成功");
          getList();
        });
      })
      .catch(() => {
        proxy.$modal.msg("已取消");
      });
  };
  // 导出
  const handleOut = () => {
    ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
      confirmButtonText: "确认",
      cancelButtonText: "取消",
      type: "warning",
    })
      .then(() => {
        proxy.download(
          "/productionOrder/export",
          { ...searchForm.value },
          "生产订单数据.xlsx"
        );
      })
      .catch(() => {
        proxy.$modal.msg("已取消");
      });
  };
  // 结束订单
  const handleEndOrder = row => {
    ElMessageBox.confirm(`是否确认结束订单:${row.npsNo}?`, "提示", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
    })
      .then(() => {
        const params = {
          id: row.id,
          endOrder: true,
        };
        updateProductOrder(params).then(() => {
          proxy.$modal.msgSuccess("结束订单成功");
          getList();
        });
      })
      .catch(() => {});
  };
  const handleConfirmRoute = () => {};
  onMounted(() => {
    getList();
const showProductStructure = (row) => {
  router.push({
    path: "/productionManagement/productStructureDetail",
    query: {
      id: row.id,
      bomNo: row.bomNo || "",
      productName: row.productName || "",
      productModelName: row.model || "",
      orderId: row.id,
      type: "order",
    },
  });
};
// 查看来源生产计划数据
const showSourceData = (row) => {
  // 存储点击来源按钮时传递的row参数
  sourceRowData.value = row;
  // 调用API获取来源数据
  getProductOrderSource(row.id)
    .then((res) => {
      if (res.code === 200) {
        // 直接存储返回的扁平化数据
        sourceTableData.value = res.data || [];
        sourcePage.total = sourceTableData.value.length;
        // 打开弹窗
        sourceDataDialogVisible.value = true;
      } else {
        proxy.$modal.msgError(res.msg || "获取来源数据失败");
      }
    })
    .catch((err) => {
      proxy.$modal.msgError("获取来源数据失败");
      console.error(err);
    });
};
// 表格选择数据
const handleSelectionChange = (selection) => {
  selectedRows.value = selection;
};
const handleDelete = () => {
  let ids = [];
  if (selectedRows.value.length > 0) {
    ids = selectedRows.value.map((item) => item.id);
  } else {
    proxy.$modal.msgWarning("请选择数据");
    return;
  }
  ElMessageBox.confirm("是否退回该生产订单?", "退回", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  })
    .then(() => {
      console.log(ids, "ids");
      delProductOrder(ids).then((res) => {
        proxy.$modal.msgSuccess("退回成功");
        getList();
      });
    })
    .catch(() => {
      proxy.$modal.msg("已取消");
    });
};
// 导出
const handleOut = () => {
  ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  })
    .then(() => {
      proxy.download(
        "/productionOrder/export",
        { ...searchForm.value },
        "生产订单数据.xlsx"
      );
    })
    .catch(() => {
      proxy.$modal.msg("已取消");
    });
};
// 结束订单
const handleEndOrder = (row) => {
  ElMessageBox.confirm(`是否确认结束订单:${row.npsNo}?`, "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  })
    .then(() => {
      const params = {
        id: row.id,
        endOrder: true,
      };
      updateProductOrder(params).then(() => {
        proxy.$modal.msgSuccess("结束订单成功");
        getList();
      });
    })
    .catch(() => {});
};
const handleConfirmRoute = () => {};
onMounted(() => {
  getList();
});
</script>
<style scoped lang="scss">
  .search_form {
    align-items: start;
  }
.search_form {
  align-items: start;
}
  .action-buttons {
.action-buttons {
  display: flex;
  flex-wrap: nowrap;
  gap: 8px;
}
:deep(.yellow) {
  background-color: #faf0de;
}
:deep(.pink) {
  background-color: #fae1de;
}
:deep(.red) {
  background-color: #f80202;
}
:deep(.purple) {
  background-color: #f4defa;
}
.table_list {
  margin-top: unset;
}
.process-progress-container {
  display: inline-flex;
  align-items: center;
  padding: 10px 0;
  white-space: nowrap;
  .process-step {
    display: flex;
    flex-wrap: nowrap;
    gap: 8px;
  }
  :deep(.yellow) {
    background-color: #faf0de;
  }
  :deep(.pink) {
    background-color: #fae1de;
  }
  :deep(.red) {
    background-color: #f80202;
  }
  :deep(.purple) {
    background-color: #f4defa;
  }
  .table_list {
    margin-top: unset;
  }
  .process-progress-container {
    display: inline-flex;
    align-items: center;
    padding: 10px 0;
    white-space: nowrap;
    position: relative;
    .process-step {
    .step-content {
      display: flex;
      flex-direction: column;
      align-items: center;
      position: relative;
      z-index: 1;
      .step-content {
      .step-circle {
        width: 36px;
        height: 36px;
        border-radius: 50%;
        border: 2px solid #409eff;
        display: flex;
        flex-direction: column;
        align-items: center;
        z-index: 1;
        justify-content: center;
        background-color: #fff;
        margin-bottom: 4px;
        .step-circle {
          width: 36px;
          height: 36px;
          border-radius: 50%;
          border: 2px solid #409eff;
          display: flex;
          align-items: center;
          justify-content: center;
          background-color: #fff;
          margin-bottom: 4px;
          .step-percentage {
            font-size: 11px;
            font-weight: bold;
          }
          &.is-completed {
            border-color: #67c23a;
            .step-percentage {
              color: #67c23a;
            }
          }
        .step-percentage {
          font-size: 11px;
          font-weight: bold;
        }
        .step-name {
          font-size: 12px;
          color: #606266;
          white-space: nowrap;
        &.is-completed {
          border-color: #67c23a;
          .step-percentage {
            color: #67c23a;
          }
        }
      }
      .step-line {
        width: 30px;
        height: 1px;
        background-color: #dcdfe6;
        margin: 0 -2px;
        margin-top: -20px; // 向上偏移以对齐圆心
      .step-name {
        font-size: 12px;
        color: #606266;
        white-space: nowrap;
      }
    }
    .step-line {
      width: 30px;
      height: 1px;
      background-color: #dcdfe6;
      margin: 0 -2px;
      margin-top: -20px; // 向上偏移以对齐圆心
    }
  }
}
</style>
<style lang="scss">
  .status-cell {
    font-weight: 600;
    color: #409eff;
    font-family: "Courier New", monospace;
    text-shadow: 0 1px 2px rgba(64, 158, 255, 0.2);
  }
.status-cell {
  font-weight: 600;
  color: #409eff;
  font-family: "Courier New", monospace;
  text-shadow: 0 1px 2px rgba(64, 158, 255, 0.2);
}
  .source-table-container {
    margin-top: 20px;
  }
.source-table-container {
  margin-top: 20px;
}
  .source-data-cards-container {
    display: flex;
    flex-direction: column;
    gap: 16px;
    max-height: 500px;
    overflow-y: auto;
    padding: 10px;
    background-color: #f5f7fa;
    border-radius: 4px;
    padding-bottom: 20px;
.source-data-cards-container {
  display: flex;
  flex-direction: column;
  gap: 16px;
  max-height: 500px;
  overflow-y: auto;
  padding: 10px;
  background-color: #f5f7fa;
  border-radius: 4px;
  padding-bottom: 20px;
    .source-data-card {
      background: #fff;
      border-radius: 8px;
      box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
      overflow: hidden;
  .source-data-card {
    background: #fff;
    border-radius: 8px;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
    overflow: hidden;
      .card-body {
        padding: 20px;
    .card-body {
      padding: 20px;
        .info-grid {
          display: grid;
          grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
          gap: 16px;
      .info-grid {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
        gap: 16px;
          .info-item {
            display: flex;
            flex-direction: column;
        .info-item {
          display: flex;
          flex-direction: column;
            .info-label {
              font-size: 12px;
              color: #909399;
              margin-bottom: 4px;
              font-weight: 500;
            }
          .info-label {
            font-size: 12px;
            color: #909399;
            margin-bottom: 4px;
            font-weight: 500;
          }
            .info-value {
              font-size: 14px;
              color: #303133;
              font-weight: 500;
            }
          .info-value {
            font-size: 14px;
            color: #303133;
            font-weight: 500;
          }
        }
      }
    }
  }
}
  .applyno-summary1 {
    padding: 16px 20px;
    background: #f5f7fa;
    border-bottom: 1px solid #e4e7ed;
.applyno-summary1 {
  padding: 16px 20px;
  background: #f5f7fa;
  border-bottom: 1px solid #e4e7ed;
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  .summary-item {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
    align-items: center;
    margin-right: 20px;
    .summary-item {
      display: flex;
      align-items: center;
      margin-right: 20px;
    .summary-label {
      font-size: 13px;
      color: #909399;
      margin-right: 8px;
      font-weight: 500;
    }
      .summary-label {
        font-size: 13px;
        color: #909399;
        margin-right: 8px;
        font-weight: 500;
      }
      .summary-value {
        font-size: 14px;
        color: #303133;
        font-weight: 500;
      }
    .summary-value {
      font-size: 14px;
      color: #303133;
      font-weight: 500;
    }
  }
}
</style>