已修改6个文件
363 ■■■■■ 文件已修改
src/api/salesManagement/salesLedger.js 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/approvalProcess/index.vue 32 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/salesLedger/components/ProcessFlowConfigSelectDialog.vue 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/salesLedger/index.vue 247 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/salesManagement/salesLedger.js
@@ -230,14 +230,6 @@
  })
}
// 标记订单完成
export function markOrderCompleted(data) {
  return request({
    url: "/sales/ledger/markOrderCompleted",
    method: "post",
    data,
  })
}
// 递增打印次数
export function incrementPrintCount(data) {
src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue
@@ -45,6 +45,32 @@
            </el-form-item>
          </el-col>
        </el-row>
        <!-- 请假/出差时间(当 approveType 为 2 或 3 时显示) -->
        <el-row :gutter="30"
                v-if="props.approveType == 2 || props.approveType == 3">
          <el-col :span="12">
            <el-form-item :label="props.approveType == 2 ? '请假开始时间:' : '开始时间:'"
                          prop="startDate">
              <el-date-picker v-model="form.startDate"
                              type="date"
                              value-format="YYYY-MM-DD"
                              format="YYYY-MM-DD"
                              disabled
                              style="width: 100%" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item :label="props.approveType == 2 ? '请假结束时间:' : '结束时间:'"
                          prop="endDate">
              <el-date-picker v-model="form.endDate"
                              type="date"
                              value-format="YYYY-MM-DD"
                              format="YYYY-MM-DD"
                              disabled
                              style="width: 100%" />
            </el-form-item>
          </el-col>
        </el-row>
        <!-- 审批人选择(动态节点) -->
        <el-row :gutter="30">
          <el-col :span="12">
@@ -457,6 +483,8 @@
      approveDeptId: "",
      approveReason: "",
      checkResult: "",
      startDate: "",
      endDate: "",
    },
  });
  const { form } = toRefs(data);
src/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue
@@ -47,11 +47,11 @@
            </el-form-item>
          </el-col>
        </el-row>
        <!-- 请假时间(仅当 approveType 为 2 时显示) -->
        <!-- 请假/出差时间(当 approveType 为 2 或 3 时显示) -->
        <el-row :gutter="30"
                v-if="props.approveType == 2">
                v-if="props.approveType == 2 || props.approveType == 3">
          <el-col :span="12">
            <el-form-item label="请假开始时间:"
            <el-form-item :label="props.approveType == 2 ? '请假开始时间:' : '开始时间:'"
                          prop="startDate">
              <el-date-picker v-model="form.startDate"
                              type="date"
@@ -63,7 +63,7 @@
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="请假结束时间:"
            <el-form-item :label="props.approveType == 2 ? '请假结束时间:' : '结束时间:'"
                          prop="endDate">
              <el-date-picker v-model="form.endDate"
                              type="date"
@@ -258,10 +258,10 @@
      approveReason: [{ required: true, message: "请输入", trigger: "blur" }],
      checkResult: [{ required: false, message: "请输入", trigger: "blur" }],
      startDate: [
        { required: true, message: "请选择请假开始时间", trigger: "change" },
        { required: true, message: "请选择开始时间", trigger: "change" },
      ],
      endDate: [
        { required: true, message: "请选择请假结束时间", trigger: "change" },
        { required: true, message: "请选择结束时间", trigger: "change" },
      ],
      price: [{ required: true, message: "请输入报销金额", trigger: "blur" }],
      location: [{ required: true, message: "请输入出差地点", trigger: "blur" }],
@@ -388,19 +388,19 @@
      proxy.$modal.msgError("请为所有审批节点选择审批人!");
      return;
    }
    // 当 approveType 为 2 时,校验请假时间
    if (props.approveType == 2) {
    // 当 approveType 为 2 或 3 时,校验请假/出差时间
    if (props.approveType == 2 || props.approveType == 3) {
      if (!form.value.startDate) {
        proxy.$modal.msgError("请选择请假开始时间!");
        proxy.$modal.msgError(props.approveType == 2 ? "请选择请假开始时间!" : "请选择开始时间!");
        return;
      }
      if (!form.value.endDate) {
        proxy.$modal.msgError("请选择请假结束时间!");
        proxy.$modal.msgError(props.approveType == 2 ? "请选择请假结束时间!" : "请选择结束时间!");
        return;
      }
      // 校验结束时间不能早于开始时间
      if (new Date(form.value.endDate) < new Date(form.value.startDate)) {
        proxy.$modal.msgError("请假结束时间不能早于开始时间!");
        proxy.$modal.msgError(props.approveType == 2 ? "请假结束时间不能早于开始时间!" : "结束时间不能早于开始时间!");
        return;
      }
    }
src/views/collaborativeApproval/approvalProcess/index.vue
@@ -186,6 +186,8 @@
  // 动态表格列配置,根据审批类型生成列
  const tableColumnCopy = computed(() => {
    const isLeaveType = currentApproveType.value === 2; // 请假管理
    const isBusinessTripType = currentApproveType.value === 3; // 出差管理
    const showDateRange = isLeaveType || isBusinessTripType; // 是否显示时间段
    const isReimburseType = currentApproveType.value === 4; // 报销管理
    const isQuotationType = currentApproveType.value === 6; // 报价审批
    const isPurchaseType = currentApproveType.value === 5; // 采购审批
@@ -261,20 +263,36 @@
      });
    }
    // 日期列(根据类型动态配置)
    // 基础日期列
    baseColumns.push(
      {
        label: isLeaveType ? "开始日期" : "申请日期",
        prop: isLeaveType ? "startDate" : "approveTime",
        width: 200,
        label: "申请日期",
        prop: "approveTime",
        width: 160,
      },
      {
        label: "结束日期",
        prop: isLeaveType ? "endDate" : "approveOverTime",
        width: 120,
        label: "审批日期",
        prop: "approveOverTime",
        width: 160,
      }
    );
    // 开始和结束日期列
    if (showDateRange) {
      baseColumns.push(
        {
          label: "开始日期",
          prop: "startDate",
          width: 120,
        },
        {
          label: "结束日期",
          prop: "endDate",
          width: 120,
        }
      );
    }
    // 当前审批人列
    baseColumns.push({
      label: "当前审批人",
src/views/salesManagement/salesLedger/components/ProcessFlowConfigSelectDialog.vue
@@ -60,6 +60,17 @@
              <div class="process-diagram-status" :class="{ 'is-done': Number(step.isCompleted) === 1 }">
                {{ Number(step.isCompleted) === 1 ? "已完成" : "未完成" }}
              </div>
              <div v-if="step.isCompleted" style="margin-top: 8px;">
                <el-date-picker
                  v-model="step.completedTime"
                  type="datetime"
                  placeholder="选择时间"
                  format="YYYY-MM-DD HH:mm:ss"
                  value-format="YYYY-MM-DD HH:mm:ss"
                  size="small"
                  style="width: 100%;"
                />
              </div>
            </div>
            <div v-if="idx < steps.length - 1" class="process-diagram-arrow">→</div>
          </div>
@@ -205,8 +216,16 @@
  await fetchRouteSteps(selectedRouteId.value);
};
const formatDateTime = (date) => {
  const pad = (n) => (n < 10 ? '0' + n : n);
  return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
};
const handleStepCompletedChange = (step) => {
  step.isCompleted = Boolean(step.isCompleted);
  if (step.isCompleted && !step.completedTime) {
    step.completedTime = proxy?.parseTime ? proxy.parseTime(new Date()) : formatDateTime(new Date());
  }
};
const handleClose = () => {
@@ -227,6 +246,7 @@
      recordList: steps.value.map((step) => ({
        processRouteItemId: step.processRouteItemId,
        isCompleted: Number(step.isCompleted ?? 0),
        completedTime: step.completedTime || (step.isCompleted ? (proxy?.parseTime ? proxy.parseTime(new Date()) : formatDateTime(new Date())) : null)
      })),
    });
  } catch (e) {
@@ -253,9 +273,9 @@
}
.process-diagram-node {
  width: 160px;
  min-width: 160px;
  height: 78px;
  width: 180px;
  min-width: 180px;
  min-height: 78px;
  border: 1px solid #ebeef5;
  border-radius: 10px;
  background: #fff;
src/views/salesManagement/salesLedger/index.vue
@@ -94,19 +94,6 @@
                                :disabled="isReviewedEdit" />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="交货日期:"
                            prop="deliveryDate">
                <el-date-picker style="width: 100%"
                                v-model="form.deliveryDate"
                                value-format="YYYY-MM-DD"
                                format="YYYY-MM-DD"
                                type="date"
                                placeholder="请选择"
                                clearable
                                :disabled="isReviewedEdit" />
              </el-form-item>
            </el-col>
          </el-row>
          <el-row :gutter="30">
            <el-col :span="12">
@@ -796,11 +783,11 @@
                         placeholder="请选择"
                         clearable
                         style="width: 100%">
                <el-option label="未发货" :value="1" />
                <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-option label="已出库" :value="5" />
                <el-option label="部分发货" :value="6" />
              </el-select>
            </el-form-item>
@@ -814,17 +801,6 @@
                <el-option label="未入库" :value="0" />
                <el-option label="部分入库" :value="1" />
                <el-option label="已入库" :value="2" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="8" :lg="8">
            <el-form-item label="订单状态:">
              <el-select v-model="searchForm.orderStatus"
                         placeholder="请选择"
                         clearable
                         style="width: 100%">
                <el-option label="进行中" :value="0" />
                <el-option label="已完成" :value="1" />
              </el-select>
            </el-form-item>
          </el-col>
@@ -873,9 +849,6 @@
            <el-button type="primary"
                       @click="handleReverseAudit"
                       :disabled="isBatchButtonDisabled('reverseAudit')">反审</el-button>
            <el-button type="warning"
                       @click="handleMarkCompleted"
                       :disabled="isBatchButtonDisabled('markCompleted')">标记完成</el-button>
            <el-button type="primary"
                       @click="handleSalesStock"
                       :disabled="isBatchButtonDisabled('stock')">入库</el-button>
@@ -893,9 +866,6 @@
            <el-button type="primary"
                       @click="handleReverseAudit"
                       :disabled="isBatchButtonDisabled('reverseAudit')">反审</el-button>
            <el-button type="warning"
                       @click="handleMarkCompleted"
                       :disabled="isBatchButtonDisabled('markCompleted')">标记完成</el-button>
            <el-button type="primary"
                       @click="handleBulkDelivery"
                       :disabled="isBatchButtonDisabled('delivery')">发货</el-button>
@@ -904,27 +874,12 @@
          <el-space v-else-if="activeStatusTab === 'delivered'"
                    wrap
                    class="sales-ledger-toolbar-group">
            <el-button type="warning"
                       @click="handleMarkCompleted"
                       :disabled="isBatchButtonDisabled('markCompleted')">标记完成</el-button>
            <el-button type="primary"
                       @click="handleReverseAudit"
                       :disabled="isBatchButtonDisabled('reverseAudit')">反审</el-button>
            <el-button @click="handleOut">导出</el-button>
          </el-space>
          <el-space v-else-if="activeStatusTab === 'completed'"
                    wrap
                    class="sales-ledger-toolbar-group">
            <el-button @click="handleOut">导出</el-button>
            <el-button type="primary"
                       plain
                       @click="handlePrintCommand('salesOrder')"
                       :disabled="isBatchButtonDisabled('print')">打印单据</el-button>
            <el-button type="primary"
                       plain
                       @click="handlePrintLabel"
                       :disabled="isBatchButtonDisabled('print')">打印标签</el-button>
          </el-space>
          <el-space v-else-if="activeStatusTab === 'all'"
                    wrap
                    class="sales-ledger-toolbar-group">
@@ -1026,7 +981,7 @@
                         align="center">
          <template #default="scope">
            <el-tag v-if="Number(scope.row.deliveryStatus) === 1"
                    type="info">未发货</el-tag>
                    type="info">未出库</el-tag>
            <el-tag v-else-if="Number(scope.row.deliveryStatus) === 2"
                    type="warning">审批中</el-tag>
            <el-tag v-else-if="Number(scope.row.deliveryStatus) === 3"
@@ -1034,7 +989,7 @@
            <el-tag v-else-if="Number(scope.row.deliveryStatus) === 4"
                    type="primary">审批通过</el-tag>
            <el-tag v-else-if="Number(scope.row.deliveryStatus) === 5"
                    type="success">已发货</el-tag>
                    type="success">已出库</el-tag>
            <el-tag v-else-if="Number(scope.row.deliveryStatus) === 6"
                    type="warning">部分发货</el-tag>
            <el-tag v-else
@@ -1069,16 +1024,6 @@
                    type="warning">审批中</el-tag>
            <el-tag v-else
                    type="info">-</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="订单状态"
                         min-width="90"
                         align="center">
          <template #default="scope">
            <el-tag v-if="Number(scope.row.orderStatus) === 1"
                    type="success">已完成</el-tag>
            <el-tag v-else
                    type="info">进行中</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="标签打印"
@@ -1122,19 +1067,17 @@
          <template #default="scope">
            <el-button link
                       type="primary"
                       @click="openForm('edit', scope.row)"
                       :disabled="Number(scope.row.orderStatus) === 1">编辑</el-button>
                       @click="openForm('edit', scope.row)">编辑</el-button>
            <el-button link
                       type="primary"
                       @click="openProcessFlowSelect(scope.row)"
                       :disabled="Number(scope.row.reviewStatus) !== 1 || Number(scope.row.orderStatus) === 1">工艺路线</el-button>
                       :disabled="Number(scope.row.reviewStatus) !== 1">工艺路线</el-button>
            <el-button link
                       type="primary"
                       @click="downLoadFile(scope.row)">附件</el-button>
            <el-button link
                       type="primary"
                       @click="openLedgerQrDialog(scope.row)"
                       :disabled="Number(scope.row.orderStatus) === 1">二维码</el-button>
                       @click="openLedgerQrDialog(scope.row)">二维码</el-button>
          </template>
        </el-table-column>
      </el-table>
@@ -1174,9 +1117,9 @@
    </template>
    <FormDialog v-if="!isFormPageMode"
                v-model="dialogFormVisible"
                :title="isCompletedOrder ? '查看销售台账页面(已完成)' : operationType === 'add' ? '新增销售台账页面' : operationType === 'view' ? '查看销售台账页面' : '编辑销售台账页面'"
                :title="operationType === 'add' ? '新增销售台账页面' : operationType === 'view' ? '查看销售台账页面' : '编辑销售台账页面'"
                :width="'70%'"
                :operation-type="isCompletedOrder || operationType === 'view' ? 'detail' : operationType"
                :operation-type="operationType === 'view' ? 'detail' : operationType"
                @close="closeDia"
                @confirm="submitForm"
                @cancel="closeDia">
@@ -1265,19 +1208,7 @@
                              :disabled="operationType === 'view' || isReviewedEdit" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="交货日期:"
                          prop="deliveryDate">
              <el-date-picker style="width: 100%"
                              v-model="form.deliveryDate"
                              value-format="YYYY-MM-DD"
                              format="YYYY-MM-DD"
                              type="date"
                              placeholder="请选择"
                              clearable
                              :disabled="operationType === 'view' || isReviewedEdit" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
@@ -1859,9 +1790,9 @@
                         :on-success="handleUploadSuccess"
                         :on-remove="handleRemove">
                <el-button type="primary"
                           v-if="operationType !== 'view' || isCompletedOrder">上传</el-button>
                           v-if="operationType !== 'view'">上传</el-button>
                <template #tip
                          v-if="operationType !== 'view' || isCompletedOrder">
                          v-if="operationType !== 'view'">
                  <div class="el-upload__tip">
                    文件格式支持
                    doc,docx,xls,xlsx,ppt,pptx,pdf,txt,xml,jpg,jpeg,png,gif,bmp,rar,zip,7z
@@ -2623,7 +2554,6 @@
    getSalesLabel,
    salesStock,
    counterReview,
    markOrderCompleted,
    incrementPrintCount,
  } from "@/api/salesManagement/salesLedger.js";
  import { modelList, productTreeList } from "@/api/basicData/product.js";
@@ -2655,7 +2585,7 @@
  const tableLoading = ref(false);
  const page = reactive({
    current: 1,
    size: 100,
    size: 50,
  });
  const total = ref(0);
  const fileList = ref([]);
@@ -2835,8 +2765,7 @@
  // 用户信息表单弹框数据
  const operationType = ref("");
  const dialogFormVisible = ref(false);
  // 已完成订单标记:view 模式但附件上传仍可用
  const isCompletedOrder = ref(false);
  // 已审核订单编辑模式:只能修改单价,其他字段禁用
  const isReviewedEdit = ref(false);
  const data = reactive({
@@ -2849,10 +2778,9 @@
      entryDate: null, // 录入日期
      entryDateStart: undefined,
      entryDateEnd: undefined,
      deliveryStatus: undefined, // 发货状态:1未发货 2审批中 3审批不通过 4审批通过 5已发货 6部分发货
      deliveryStatus: undefined, // 发货状态:1未出库 2审批中 3审批不通过 4审批通过 5已出库 6部分发货
      stockStatus: undefined, // 入库状态:0未入库 1部分入库 2已入库
      reviewStatus: undefined, // 审核状态:0待审核 1已审核 2已反审
      orderStatus: undefined, // 订单状态:0进行中 1已完成
    },
    form: {
      salesContractNo: "",
@@ -2872,23 +2800,14 @@
      customerId: [{ required: true, message: "请选择", trigger: "change" }],
      entryPerson: [{ required: true, message: "请选择", trigger: "change" }],
      entryDate: [{ required: true, message: "请选择", trigger: "change" }],
      deliveryDate: [{ required: true, message: "请选择", trigger: "change" }],
      executionDate: [{ required: true, message: "请选择", trigger: "change" }],
    },
  });
  const { form, rules } = toRefs(data);
  const { form: searchForm } = useFormData(data.searchForm);
  // 新增台账:录入日期变更时,交货日期默认保持为录入日期后第 7 天
  watch(
    () => [operationType.value, form.value?.entryDate],
    () => {
      if (operationType.value !== "add") return;
      const ed = form.value?.entryDate;
      if (!ed) return;
      form.value.deliveryDate = dayjs(ed).add(7, "day").format("YYYY-MM-DD");
    }
  );
  // 产品表单弹框数据
  const productFormVisible = ref(false);
  const productOperationType = ref("");
@@ -3161,7 +3080,7 @@
    if (operationType.value === "view") return;
    if (!row) return;
    if (isProductShipped(row)) {
      proxy.$modal.msgWarning("已发货或审核通过的产品不能复制");
      proxy.$modal.msgWarning("已出库或审核通过的产品不能复制");
      return;
    }
    const hasBlockingEditingRow = (productData.value || []).some(
@@ -3243,7 +3162,7 @@
    if (operationType.value === "view") return;
    if (!row) return;
    if (isProductShipped(row)) {
      proxy.$modal.msgWarning("已发货或审核通过的产品不能编辑");
      proxy.$modal.msgWarning("已出库或审核通过的产品不能编辑");
      return;
    }
    if (!discardPlaceholderRowIfPristine()) return;
@@ -3345,7 +3264,7 @@
    if (operationType.value === "view") return;
    if (!row) return;
    if (isProductShipped(row)) {
      proxy.$modal.msgWarning("已发货或审核通过的产品不能编辑");
      proxy.$modal.msgWarning("已出库或审核通过的产品不能编辑");
      return;
    }
    // 确保 productForm 指向当前行,以复用计算逻辑
@@ -3442,7 +3361,7 @@
    if (!row) return;
    if (operationType.value === "view") return;
    if (isProductShipped(row)) {
      proxy.$modal.msgWarning("已发货或审核通过的产品不能编辑");
      proxy.$modal.msgWarning("已出库或审核通过的产品不能编辑");
      return;
    }
    ensureProductRowDefaults(row);
@@ -3492,7 +3411,7 @@
    if (!row) return;
    if (operationType.value === "view") return;
    if (isProductShipped(row)) {
      proxy.$modal.msgWarning("已发货或审核通过的产品不能编辑");
      proxy.$modal.msgWarning("已出库或审核通过的产品不能编辑");
      return;
    }
    ensureProductRowDefaults(row);
@@ -3911,8 +3830,8 @@
    shipped: "/sales/ledger/salesHistory/shippingImportTemplate",
  };
  const HISTORY_IMPORT_TEMPLATE_FILE_NAME_MAP = {
    notShipped: "销售发货历史数据导入模板-未发货.xlsx",
    shipped: "销售发货历史数据导入模板-已发货.xlsx",
    notShipped: "销售发货历史数据导入模板-未出库.xlsx",
    shipped: "销售发货历史数据导入模板-已出库.xlsx",
  };
  const currentImportCommand = ref("default");
  const activeStatusTab = ref("all");
@@ -3922,15 +3841,13 @@
    { key: "reviewed", label: "已审核" },
    { key: "reverseReviewed", label: "反审核" },
    { key: "stocked", label: "已入库" },
    { key: "delivered", label: "已发货" },
    { key: "completed", label: "已完成" },
    { key: "delivered", label: "已出库" },
  ];
  const resetStatusFilters = () => {
    searchForm.reviewStatus = undefined;
    searchForm.stockStatus = undefined;
    searchForm.deliveryStatus = undefined;
    searchForm.orderStatus = undefined;
  };
  const handleStatusTabChange = tabKey => {
@@ -3954,9 +3871,6 @@
      case "delivered":
        searchForm.deliveryStatus = 5;
        break;
      case "completed":
        searchForm.orderStatus = 1;
        break;
      default:
        break;
    }
@@ -3973,17 +3887,13 @@
    handleQuery();
  };
  /** 批量按钮禁用判断:根据选中行的审核状态和订单状态控制按钮可用性
  /** 批量按钮禁用判断:根据选中行的审核状态控制按钮可用性
   *  未审核(0):只能审核、删除、编辑
   *  已审核(1):可以反审、入库、发货、导出、打印、工艺路线
   *  已完成(orderStatus=1):所有操作按钮禁用
   *  未选中任何行时所有批量按钮禁用
   */
  const isBatchButtonDisabled = (action) => {
    if (selectedRows.value.length === 0) return true;
    const hasCompleted = selectedRows.value.some(r => Number(r.orderStatus) === 1);
    // 已完成订单:所有操作按钮禁用
    if (hasCompleted && action !== 'markCompleted') return true;
    const statuses = selectedRows.value.map(r => Number(r.reviewStatus));
    const allUnreviewed = statuses.every(s => s === 0);
    const allReviewed = statuses.every(s => s === 1);
@@ -4002,9 +3912,6 @@
        return !allUnreviewed;
      case 'print':
        return !allReviewed;
      case 'markCompleted':
        // 只有已审核且未完成的订单才能标记完成
        return !allReviewed || hasCompleted;
      default:
        return false;
    }
@@ -4123,33 +4030,7 @@
    }
  };
  /** 标记完成操作 */
  const handleMarkCompleted = async () => {
    if (selectedRows.value.length === 0) {
      proxy.$modal.msgWarning("请选择要标记完成的数据");
      return;
    }
    const cannotComplete = selectedRows.value.filter(
      row => Number(row.reviewStatus) !== 1 || Number(row.orderStatus) === 1
    );
    if (cannotComplete.length > 0) {
      proxy.$modal.msgWarning("选中的数据中包含非已审核或已完成的项,请重新选择");
      return;
    }
    try {
      await ElMessageBox.confirm(
        "标记完成后订单将变为只读,只能查看和上传下载附件,不可撤销。是否确认?",
        "提示",
        { confirmButtonText: "确定", cancelButtonText: "取消", type: "warning" }
      );
      const ids = selectedRows.value.map(row => row.id);
      await markOrderCompleted({ ids });
      proxy.$modal.msgSuccess("标记完成成功");
      getList();
    } catch {
      // 用户取消
    }
  };
  /** 用预填数据打开新增台账页面(重新生成场景) */
  const openFormWithPreFill = async (detail, keepPageMode = false) => {
@@ -4172,13 +4053,11 @@
    form.value.entryPerson = Number(userStore.id);
    form.value.entryDate = getCurrentDate();
    form.value.executionDate = detail.executionDate || getCurrentDate();
    form.value.deliveryDate = detail.deliveryDate;
    form.value.paymentMethod = detail.paymentMethod;
    form.value.contractAmount = detail.contractAmount;
    form.value.remarks = detail.remarks;
    form.value.customerRemarks = detail.customerRemarks ?? detail.customer_remarks ?? "";
    productData.value = detail.productData || [];
    form.value.deliveryDate = dayjs(form.value.entryDate).add(7, "day").format("YYYY-MM-DD");
    await appendEditablePlaceholderRow();
    dialogFormVisible.value = !keepPageMode;
  };
@@ -4646,7 +4525,7 @@
  // 添加表行类名方法
  const tableRowClassName = ({ row }) => {
    if (!row.deliveryDate) return "";
    if (!row.deliveryDate || row.stockStatus === 0) return "";
    if (row.isFh) return "";
    const diff = row.deliveryDaysDiff;
@@ -4690,7 +4569,6 @@
  const initAddFormState = async () => {
    operationType.value = "add";
    isCompletedOrder.value = false;
    isReviewedEdit.value = false;
    form.value = {};
    productData.value = [];
@@ -4708,15 +4586,11 @@
    form.value.entryDate = getCurrentDate();
    form.value.executionDate = getCurrentDate();
    form.value.customerRemarks = "";
    form.value.deliveryDate = dayjs(form.value.entryDate)
      .add(7, "day")
      .format("YYYY-MM-DD");
    await appendEditablePlaceholderRow();
  };
  const initEditFormState = async rowId => {
    operationType.value = "edit";
    isCompletedOrder.value = false;
    form.value = {};
    productData.value = [];
    fileList.value = [];
@@ -4792,16 +4666,12 @@
      await enterEditPage(row);
      return;
    }
    // 已完成订单强制为只读模式,但附件上传仍可用
    const isCompleted = Number(row?.orderStatus) === 1;
    const effectiveType = isCompleted ? 'view' : type;
    operationType.value = effectiveType;
    isCompletedOrder.value = isCompleted;
    operationType.value = type;
    form.value = {};
    productData.value = [];
    selectedQuotation.value = null;
    // 已审核订单编辑时,标记只能修改单价(已完成订单已强制view,此处不会再命中)
    isReviewedEdit.value = effectiveType === "edit" && Number(row?.reviewStatus) === 1;
    // 已审核订单编辑时,标记只能修改单价
    isReviewedEdit.value = type === "edit" && Number(row?.reviewStatus) === 1;
    let userLists = await userListNoPage();
    userList.value = userLists.data;
    customerList().then(res => {
@@ -4833,11 +4703,7 @@
    //   }
    // });
    form.value.entryDate = getCurrentDate(); // 设置默认录入日期为当前日期
    if (type === "add") {
      form.value.deliveryDate = dayjs(form.value.entryDate)
        .add(7, "day")
        .format("YYYY-MM-DD");
    }
    dialogFormVisible.value = true;
  };
@@ -5067,7 +4933,6 @@
      proxy.resetForm("formRef");
    }
    dialogFormVisible.value = false;
    isCompletedOrder.value = false;
    isReviewedEdit.value = false;
    if (!isFormPageMode.value) {
      fileList.value = [];
@@ -5077,9 +4942,9 @@
  const productIndex = ref(0);
  // 打开产品弹框
  const openProductForm = async (type, row, index) => {
    // 编辑时检查产品是否已发货或审核通过
    // 编辑时检查产品是否已出库或审核通过
    if (type === "edit" && isProductShipped(row)) {
      proxy.$modal.msgWarning("已发货或审核通过的产品不能编辑");
      proxy.$modal.msgWarning("已出库或审核通过的产品不能编辑");
      return;
    }
@@ -5231,12 +5096,12 @@
      return;
    }
    // 检查是否有已发货或审核通过的产品
    // 检查是否有已出库或审核通过的产品
    const shippedProducts = productSelectedRows.value.filter(row =>
      isProductShipped(row)
    );
    if (shippedProducts.length > 0) {
      proxy.$modal.msgWarning("已发货或审核通过的产品不能删除");
      proxy.$modal.msgWarning("已出库或审核通过的产品不能删除");
      return;
    }
@@ -5439,24 +5304,24 @@
    );
    exportProcessRouteDialogVisible.value = false;
  };
  /** 判断单个产品是否已发货(根据shippingStatus判断,已发货或审核通过不可编辑和删除) */
  /** 判断单个产品是否已出库(根据shippingStatus判断,已出库或审核通过不可编辑和删除) */
  const isProductShipped = product => {
    if (!product) return false;
    const status = String(product.shippingStatus || "").trim();
    // 如果发货状态是"已发货"或"审核通过",则不可编辑和删除
    return status === "已发货" || status === "审核通过";
    // 如果发货状态是"已出库"或"审核通过",则不可编辑和删除
    return status === "已出库" || status === "审核通过";
  };
  /** 判断销售订单下是否存在已发货/发货完成的产品(不可删除) */
  /** 判断销售订单下是否存在已出库/发货完成的产品(不可删除) */
  const hasShippedProducts = products => {
    if (!products || !products.length) return false;
    return products.some(p => {
      const status = String(p.shippingStatus || "").trim();
      // 有发货日期或车牌号视为已发货
      // 有发货日期或车牌号视为已出库
      if (p.shippingDate || p.shippingCarNumber) return true;
      // 已进行发货、发货完成、已发货 均不可删除
      // 已进行发货、发货完成、已出库 均不可删除
      return (
        status === "已进行发货" || status === "发货完成" || status === "已发货"
        status === "已进行发货" || status === "发货完成" || status === "已出库"
      );
    });
  };
@@ -5972,9 +5837,9 @@
   * @param row 行数据
   */
  const getShippingStatusText = row => {
    // 如果已发货(有发货日期或车牌号),显示"已发货"
    // 如果已出库(有发货日期或车牌号),显示"已出库"
    if (row.shippingDate || row.shippingCarNumber) {
      return "已发货";
      return "已出库";
    }
    // 获取发货状态字段
@@ -5993,7 +5858,7 @@
      审核中: "审核中",
      审核拒绝: "审核拒绝",
      审核通过: "审核通过",
      已发货: "已发货",
      已出库: "已出库",
    };
    return statusTextMap[statusStr] || "待发货";
  };
@@ -6003,7 +5868,7 @@
   * @param row 行数据
   */
  const getShippingStatusType = row => {
    // 如果已发货(有发货日期或车牌号),显示绿色
    // 如果已出库(有发货日期或车牌号),显示绿色
    if (row.shippingDate || row.shippingCarNumber) {
      return "success";
    }
@@ -6024,7 +5889,7 @@
      审核中: "warning",
      审核拒绝: "danger",
      审核通过: "success",
      已发货: "success",
      已出库: "success",
    };
    return typeTextMap[statusStr] || "info";
  };
@@ -6040,7 +5905,7 @@
      return false;
    }
    // 台账级发货状态(deliveryStatus):2审批中、5已发货 时不可再发起本行发货;6部分发货仍可按明细继续发
    // 台账级发货状态(deliveryStatus):2审批中、5已出库 时不可再发起本行发货;6部分发货仍可按明细继续发
    const deliveryStatus = row.deliveryStatus;
    if (
      deliveryStatus !== null &&
@@ -6054,7 +5919,7 @@
    // 获取发货状态
    const shippingStatus = row.shippingStatus;
    // 如果已发货(有发货日期或车牌号),不能再次发货
    // 如果已出库(有发货日期或车牌号),不能再次发货
    if (row.shippingDate || row.shippingCarNumber) {
      return false;
    }
@@ -6104,14 +5969,14 @@
      return;
    }
    // 允许:1未发货、3审批不通过、4审批通过、6部分发货;不允许:2审批中、5已发货
    // 允许:1未出库、3审批不通过、4审批通过、6部分发货;不允许:2审批中、5已出库
    const statusItem = selectedRows.value[0].deliveryStatus;
    const ledgerAllowsDelivery = s => [1, 3, 4, 6].includes(Number(s));
    let isTrue = true;
    selectedRows.value.forEach(row => {
      if (!ledgerAllowsDelivery(row.deliveryStatus)) {
        proxy.$modal.msgWarning(
          "仅未发货、审批不通过、审批通过或部分发货的台账可以发货"
          "仅未出库、审批不通过、审批通过或部分发货的台账可以发货"
        );
        isTrue = false;
        return;
@@ -6155,7 +6020,7 @@
    );
    if (shippedLedgers.length === selectedRows.value.length) {
      try {
        await ElMessageBox.alert("所选销售台账均已发货,不能再次发货。", "提示", {
        await ElMessageBox.alert("所选销售台账均已出库,不能再次发货。", "提示", {
          type: "warning",
          confirmButtonText: "知道了",
        });
@@ -6167,7 +6032,7 @@
    if (shippedLedgers.length > 0) {
      try {
        await ElMessageBox.alert(
          "选中的销售台账中包含已发货记录,已发货的不能再次发货,系统将仅为未发货台账处理。",
          "选中的销售台账中包含已出库记录,已出库的不能再次发货,系统将仅为未出库台账处理。",
          "提示",
          {
            type: "warning",
@@ -6269,7 +6134,7 @@
    const status = Number(row.deliveryStatus);
    if (![1, 3, 4, 6].includes(status)) {
      proxy.$modal.msgWarning(
        "只有发货状态为未发货、审批不通过、审批通过或部分发货的记录才可以发货"
        "只有发货状态为未出库、审批不通过、审批通过或部分发货的记录才可以发货"
      );
      return;
    }