gongchunyi
2026-06-22 dfad6a2a0faa1c2ebd31640dcc865013a2017b1b
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">
@@ -211,8 +198,7 @@
                             prop="thickness"
                             min-width="95">
              <template #default="scope">
                <el-input-number v-if="scope.row.__editing"
                                 controls-position="right"
                <el-input-number :controls="false" v-if="scope.row.__editing"
                                 v-model="scope.row.thickness"
                                 :min="0"
                                 :step="1"
@@ -243,7 +229,7 @@
                             min-width="85">
              <template #default="scope">
                <el-input-number v-if="scope.row.__editing"
                                 controls-position="right"
                                 :controls="false"
                                 :step="0.01"
                                 :min="0"
                                 :precision="2"
@@ -261,7 +247,7 @@
                             min-width="85">
              <template #default="scope">
                <el-input-number v-if="scope.row.__editing"
                                 controls-position="right"
                                 :controls="false"
                                 v-model="scope.row.width"
                                 :min="0"
                                 :step="1"
@@ -280,7 +266,7 @@
                             min-width="85">
              <template #default="scope">
                <el-input-number v-if="scope.row.__editing"
                                 controls-position="right"
                                 :controls="false"
                                 v-model="scope.row.height"
                                 :min="0"
                                 :step="1"
@@ -298,8 +284,7 @@
                             prop="quantity"
                             min-width="85">
              <template #default="scope">
                <el-input-number v-if="scope.row.__editing"
                                 controls-position="right"
                <el-input-number :controls="false" v-if="scope.row.__editing"
                                 v-model="scope.row.quantity"
                                 :step="1"
                                 :min="0"
@@ -317,8 +302,7 @@
                             prop="settlePieceArea"
                             min-width="120">
              <template #default="scope">
                <el-input-number v-if="scope.row.__editing"
                                 controls-position="right"
                <el-input-number :controls="false" v-if="scope.row.__editing"
                                 v-model="scope.row.settlePieceArea"
                                 :min="0"
                                 :step="1"
@@ -335,8 +319,7 @@
                             prop="actualTotalArea"
                             min-width="110">
              <template #default="scope">
                <el-input-number v-if="scope.row.__editing"
                                 controls-position="right"
                <el-input-number :controls="false" v-if="scope.row.__editing"
                                 v-model="scope.row.actualTotalArea"
                                 :min="0"
                                 :step="1"
@@ -513,7 +496,7 @@
                                style="max-width: 170px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;">
                          {{ item.processName }}
                        </el-tag>
                        <el-input-number v-model="item.quantity"
                        <el-input-number :controls="false" v-model="item.quantity"
                                         :min="0"
                                         :step="1"
                                         :precision="0"
@@ -624,7 +607,7 @@
                                style="max-width: 170px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;">
                          {{ item.processName }}
                        </el-tag>
                        <el-input-number v-model="item.quantity"
                        <el-input-number :controls="false" v-model="item.quantity"
                                         :min="0"
                                         :step="1"
                                         :precision="0"
@@ -708,182 +691,241 @@
      </div>
    </template>
    <template v-else>
    <div class="sales-ledger-status-bar">
      <button v-for="tab in salesLedgerStatusTabs"
              :key="tab.key"
              type="button"
              class="sales-ledger-status-tab"
              :class="{ 'is-active': activeStatusTab === tab.key }"
              @click="handleStatusTabChange(tab.key)">
        {{ tab.label }}
      </button>
    </div>
    <ReverseAuditHistory v-if="activeStatusTab === 'reverseReviewed'" />
    <div v-else>
    <div class="search_form">
      <el-form :model="searchForm"
               :inline="true">
        <el-form-item label="客户名称:">
          <el-select v-model="searchForm.customerId"
                     filterable
                     placeholder="请选择客户名称"
                     clearable
                     style="width: 220px"
                     @change="handleQuery">
            <el-option v-for="item in customerOption"
                       :key="item.id"
                       :label="item.customerName"
                       :value="item.id">
              {{ item.customerName + "——" + item.taxpayerIdentificationNumber }}
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="销售合同号:">
          <el-input v-model="searchForm.salesContractNo"
                    placeholder="请输入"
                    clearable
                    prefix-icon="Search"
                    @change="handleQuery" />
        </el-form-item>
        <el-form-item label="项目名称:">
          <el-input v-model="searchForm.projectName"
                    placeholder="请输入"
                    clearable
                    prefix-icon="Search"
                    @change="handleQuery" />
        </el-form-item>
        <el-form-item label="产品宽(mm):">
          <el-input v-model="searchForm.width"
                    placeholder="请输入"
                    clearable
                    prefix-icon="Search"
                    @change="handleQuery" />
        </el-form-item>
        <el-form-item label="产品高(mm):">
          <el-input v-model="searchForm.height"
                    placeholder="请输入"
                    clearable
                    prefix-icon="Search"
                    @change="handleQuery" />
        </el-form-item>
        <el-form-item label="录入日期:">
          <el-date-picker v-model="searchForm.entryDate"
                          value-format="YYYY-MM-DD"
                          format="YYYY-MM-DD"
                          type="daterange"
                          placeholder="请选择"
                          clearable
                          @change="changeDaterange" />
        </el-form-item>
        <el-form-item label="发货状态:">
          <el-select v-model="searchForm.deliveryStatus"
                     placeholder="请选择"
                     clearable
                     style="width: 140px">
            <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="6" />
          </el-select>
        </el-form-item>
        <el-form-item label="入库状态:">
          <el-select v-model="searchForm.stockStatus"
                     placeholder="请选择"
                     clearable
                     style="width: 140px">
            <el-option label="未入库"
                       :value="0" />
            <el-option label="部分入库"
                       :value="1" />
            <el-option label="已入库"
                       :value="2" />
          </el-select>
        </el-form-item>
        <el-form-item label="订单状态:">
          <el-select v-model="searchForm.orderStatus"
                     placeholder="请选择"
                     clearable
                     style="width: 140px">
            <el-option label="进行中"
                       :value="0" />
            <el-option label="已完成"
                       :value="1" />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary"
                     @click="handleQuery"> 搜索 </el-button>
        </el-form-item>
      <el-form :model="searchForm" label-width="110px">
        <el-row :gutter="20">
          <el-col :xs="24" :sm="12" :md="8" :lg="8">
            <el-form-item label="客户名称:">
              <el-select v-model="searchForm.customerId"
                         filterable
                         placeholder="请选择客户名称"
                         clearable
                         style="width: 100%"
                         @change="handleQuery">
                <el-option v-for="item in customerOption"
                           :key="item.id"
                           :label="item.customerName"
                           :value="item.id">
                  {{ item.customerName + "——" + item.taxpayerIdentificationNumber }}
                </el-option>
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="8" :lg="8">
            <el-form-item label="销售合同号:">
              <el-input v-model="searchForm.salesContractNo"
                        placeholder="请输入"
                        clearable
                        prefix-icon="Search"
                        style="width: 100%"
                        @change="handleQuery" />
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="8" :lg="8">
            <el-form-item label="项目名称:">
              <el-input v-model="searchForm.projectName"
                        placeholder="请输入"
                        clearable
                        prefix-icon="Search"
                        style="width: 100%"
                        @change="handleQuery" />
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="8" :lg="8">
            <el-form-item label="录入日期:">
              <el-date-picker v-model="searchForm.entryDate"
                              value-format="YYYY-MM-DD"
                              format="YYYY-MM-DD"
                              type="daterange"
                              placeholder="请选择"
                              clearable
                              style="width: 100%"
                              @change="changeDaterange" />
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="8" :lg="8">
            <el-form-item label="产品宽(mm):">
              <el-input v-model="searchForm.width"
                        placeholder="请输入"
                        clearable
                        prefix-icon="Search"
                        style="width: 100%"
                        @input="val => searchForm.width = val.replace(/[^\d.]/g, '')"
                        @change="handleQuery" />
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="8" :lg="8">
            <el-form-item label="产品高(mm):">
              <el-input v-model="searchForm.height"
                        placeholder="请输入"
                        clearable
                        prefix-icon="Search"
                        style="width: 100%"
                        @input="val => searchForm.height = val.replace(/[^\d.]/g, '')"
                        @change="handleQuery" />
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="8" :lg="8">
            <el-form-item label="发货状态:">
              <el-select v-model="searchForm.deliveryStatus"
                         placeholder="请选择"
                         clearable
                         style="width: 100%">
                <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="6" />
              </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.stockStatus"
                         placeholder="请选择"
                         clearable
                         style="width: 100%">
                <el-option label="未入库" :value="0" />
                <el-option label="部分入库" :value="1" />
                <el-option label="已入库" :value="2" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label=" ">
              <div style="width: 100%; text-align: right;">
                <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
              </div>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
    </div>
    <div class="table_list">
      <div class="actions">
        <div>
      <div class="actions sales-ledger-toolbar">
        <div class="sales-ledger-toolbar-group">
          <OtherAmountMaintenanceButton />
          <ProcessFlowMaintenanceButton />
        </div>
        <ProcessFlowConfigSelectDialog v-model:visible="processFlowSelectDialogVisible"
                                       :default-route-id="processFlowSelectDefaultRouteId"
                                       :default-record-list="processFlowSelectDefaultRecordList"
                                       :bound-route-name="processFlowSelectBoundRouteName"
                                       @confirm="handleProcessFlowSelectConfirm" />
        <el-space wrap>
          <el-button type="primary"
                     @click="handleAudit"
                     :disabled="isBatchButtonDisabled('audit')">审核</el-button>
          <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>
          <el-button type="primary"
                     @click="openForm('add')">新增台账</el-button>
          <el-button type="primary"
                     @click="handleBulkDelivery"
                     :disabled="isBatchButtonDisabled('delivery')">发货</el-button>
          <el-button type="primary"
                     plain
                     @click="handleImport">导入</el-button>
          <el-dropdown @command="handleHistoryImportCommand">
        <div class="sales-ledger-toolbar-actions">
          <el-space v-if="activeStatusTab === 'pendingReview'"
                    wrap
                    class="sales-ledger-toolbar-group">
            <el-button type="primary"
                       plain>
              历史迁移<el-icon class="el-icon--right">
                <ArrowDown />
              </el-icon>
            </el-button>
            <template #dropdown>
              <el-dropdown-menu>
                <el-dropdown-item command="notShipped">未出库</el-dropdown-item>
                <el-dropdown-item command="shipped">已出库</el-dropdown-item>
              </el-dropdown-menu>
            </template>
          </el-dropdown>
          <el-button @click="handleOut"
                     :disabled="isBatchButtonDisabled('export')">导出</el-button>
          <el-button type="danger"
                     plain
                     @click="handleDelete"
                     :disabled="isBatchButtonDisabled('delete')">删除</el-button>
          <el-dropdown @command="handlePrintCommand">
                       @click="handleAudit"
                       :disabled="isBatchButtonDisabled('audit')">审核</el-button>
            <el-button type="danger"
                       plain
                       @click="handleDelete"
                       :disabled="isBatchButtonDisabled('delete')">删除</el-button>
            <el-button type="primary"
                       @click="openForm('add')">新增台账</el-button>
            <el-button type="primary"
                       plain
                       :disabled="isBatchButtonDisabled('print')">
              打印单据<el-icon class="el-icon--right">
                <ArrowDown />
              </el-icon>
            </el-button>
            <template #dropdown>
              <el-dropdown-menu>
                <el-dropdown-item command="finishedProcessCard">生产流程卡(成品)</el-dropdown-item>
                <el-dropdown-item command="salesOrder">销售订单</el-dropdown-item>
                <el-dropdown-item command="salesDeliveryNote">销售发货单</el-dropdown-item>
              </el-dropdown-menu>
            </template>
          </el-dropdown>
          <el-button type="primary"
                     plain
                     @click="handlePrintLabel"
                     :disabled="isBatchButtonDisabled('print')">打印标签</el-button>
        </el-space>
                       @click="handleImport">导入</el-button>
            <el-button @click="handleOut">导出</el-button>
          </el-space>
          <el-space v-else-if="activeStatusTab === 'reviewed'"
                    wrap
                    class="sales-ledger-toolbar-group">
            <el-button type="primary"
                       @click="handleReverseAudit"
                       :disabled="isBatchButtonDisabled('reverseAudit')">反审</el-button>
            <el-button type="primary"
                       @click="handleSalesStock"
                       :disabled="isBatchButtonDisabled('stock')">入库</el-button>
            <el-button type="primary"
                       @click="handleBulkDelivery"
                       :disabled="isBatchButtonDisabled('delivery')">发货</el-button>
            <el-button @click="handleOut">导出</el-button>
            <el-button @click="handleExportProcessRoute"
                       :disabled="isBatchButtonDisabled('export')">导出工艺路线</el-button>
          </el-space>
          <el-space v-else-if="activeStatusTab === 'stocked'"
                    wrap
                    class="sales-ledger-toolbar-group">
            <el-button type="primary"
                       @click="handleReverseAudit"
                       :disabled="isBatchButtonDisabled('reverseAudit')">反审</el-button>
            <el-button type="primary"
                       @click="handleBulkDelivery"
                       :disabled="isBatchButtonDisabled('delivery')">发货</el-button>
            <el-button @click="handleOut">导出</el-button>
          </el-space>
          <el-space v-else-if="activeStatusTab === 'delivered'"
                    wrap
                    class="sales-ledger-toolbar-group">
            <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 === 'all'"
                    wrap
                    class="sales-ledger-toolbar-group">
            <el-button type="primary"
                       @click="openForm('add')">新增台账</el-button>
            <el-button @click="handleOut">导出</el-button>
          </el-space>
          <el-space wrap class="sales-ledger-toolbar-group sales-ledger-toolbar-group--muted">
            <el-dropdown @command="handleHistoryImportCommand">
              <el-button type="primary"
                         plain>
                历史迁移<el-icon class="el-icon--right">
                  <ArrowDown />
                </el-icon>
              </el-button>
              <template #dropdown>
                <el-dropdown-menu>
                  <el-dropdown-item command="notShipped">未出库</el-dropdown-item>
                  <el-dropdown-item command="shipped">已出库</el-dropdown-item>
                </el-dropdown-menu>
              </template>
            </el-dropdown>
          </el-space>
          <el-space wrap class="sales-ledger-toolbar-group sales-ledger-toolbar-group--muted">
            <el-dropdown @command="handlePrintCommand">
              <el-button type="primary"
                         plain
                         :disabled="isBatchButtonDisabled('print')">
                打印单据<el-icon class="el-icon--right">
                  <ArrowDown />
                </el-icon>
              </el-button>
              <template #dropdown>
                <el-dropdown-menu>
                  <el-dropdown-item command="finishedProcessCard">生产流程卡(成品)</el-dropdown-item>
                  <el-dropdown-item command="salesOrder">销售订单</el-dropdown-item>
                  <el-dropdown-item command="salesDeliveryNote">销售发货单</el-dropdown-item>
                </el-dropdown-menu>
              </template>
            </el-dropdown>
            <el-button type="primary"
                       plain
                       @click="handlePrintLabel"
                       :disabled="isBatchButtonDisabled('print')">打印标签</el-button>
          </el-space>
        </div>
      </div>
      <el-table :data="tableData"
                border
@@ -893,8 +935,8 @@
                :row-class-name="tableRowClassName"
                show-summary
                style="width: 100%"
                :summary-method="summarizeMainTable"
                height="calc(100vh - 22em)">
                height="calc(100vh - 23em)"
                :summary-method="summarizeMainTable">
        <el-table-column align="center"
                         type="selection"
                         width="55"
@@ -905,7 +947,7 @@
                         width="60" />
        <el-table-column label="订单号"
                         prop="salesContractNo"
                         width="180"
                         min-width="160"
                         show-overflow-tooltip>
          <template #default="scope">
            <el-button link
@@ -915,31 +957,31 @@
        </el-table-column>
        <el-table-column label="客户名称"
                         prop="customerName"
                         width="300"
                         min-width="200"
                         show-overflow-tooltip />
        <el-table-column label="业务员"
                         prop="salesman"
                         width="100"
                         min-width="80"
                         show-overflow-tooltip />
        <el-table-column label="合同金额(元)"
                         prop="contractAmount"
                         width="220"
                         min-width="120"
                         show-overflow-tooltip
                         :formatter="formattedNumber" />
        <el-table-column label="面积"
                         prop="productTotalArea"
                         width="120"
                         min-width="80"
                         show-overflow-tooltip />
        <el-table-column label="数量"
                         prop="productTotalQuantity"
                         width="120"
                         min-width="80"
                         show-overflow-tooltip />
        <el-table-column label="发货状态"
                         width="140"
                         min-width="100"
                         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"
@@ -947,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
@@ -955,19 +997,21 @@
          </template>
        </el-table-column>
        <el-table-column label="审核状态"
                         width="120"
                         min-width="90"
                         align="center">
          <template #default="scope">
            <el-tag v-if="Number(scope.row.reviewStatus) === 0"
                    type="warning">待审核</el-tag>
            <el-tag v-else-if="Number(scope.row.reviewStatus) === 1"
                    type="success">已审核</el-tag>
            <el-tag v-else-if="Number(scope.row.reviewStatus) === 2"
                    type="danger">已反审</el-tag>
            <el-tag v-else
                    type="info">待审核</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="入库状态"
                         width="120"
                         min-width="90"
                         align="center">
          <template #default="scope">
            <el-tag v-if="Number(scope.row.stockStatus) === 0"
@@ -982,25 +1026,15 @@
                    type="info">-</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="订单状态"
                         width="120"
                         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="标签打印"
                         width="90"
                         min-width="90"
                         align="center">
          <template #default="scope">
            <span>{{ scope.row.labelPrintCount ?? 0 }}</span>
          </template>
        </el-table-column>
        <el-table-column label="单据打印"
                         width="90"
                         min-width="90"
                         align="center">
          <template #default="scope">
            <span>{{ scope.row.documentPrintCount ?? 0 }}</span>
@@ -1008,44 +1042,42 @@
        </el-table-column>
        <el-table-column label="录入人"
                         prop="entryPersonName"
                         width="100"
                         min-width="80"
                         show-overflow-tooltip />
        <el-table-column label="录入日期"
                         prop="entryDate"
                         width="120"
                         min-width="110"
                         show-overflow-tooltip />
        <el-table-column label="交付日期"
                         prop="deliveryDate"
                         width="120"
                         min-width="110"
                         show-overflow-tooltip />
        <el-table-column label="备注"
                         prop="remarks"
                         width="200"
                         min-width="120"
                         show-overflow-tooltip />
        <el-table-column label="客户备注"
                         prop="customerRemarks"
                         width="200"
                         min-width="120"
                         show-overflow-tooltip />
        <el-table-column fixed="right"
                         label="操作"
                         width="280"
                         width="250"
                         align="center">
          <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>
@@ -1056,12 +1088,38 @@
                  :limit="page.size"
                  @pagination="paginationChange" />
    </div>
    </div>
    <!-- 导出工艺路线 弹窗 -->
    <el-dialog title="选择导出时间范围"
               v-model="exportProcessRouteDialogVisible"
               width="450px"
               append-to-body>
      <el-form>
        <el-form-item label="完成时间:">
          <el-date-picker v-model="processRouteExportDateRange"
                          type="datetimerange"
                          range-separator="至"
                          start-placeholder="开始时间"
                          end-placeholder="结束时间"
                          value-format="YYYY-MM-DD HH:mm:ss"
                          format="YYYY-MM-DD HH:mm:ss"
                          clearable
                          style="width: 100%;" />
        </el-form-item>
      </el-form>
      <template #footer>
        <div style="text-align: right">
          <el-button @click="exportProcessRouteDialogVisible = false">取消</el-button>
          <el-button type="primary" @click="confirmExportProcessRoute">确认导出</el-button>
        </div>
      </template>
    </el-dialog>
    </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">
@@ -1150,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">
@@ -1270,8 +1316,7 @@
                           prop="thickness"
                           min-width="95">
            <template #default="scope">
              <el-input-number v-if="scope.row.__editing"
                               controls-position="right"
              <el-input-number :controls="false" v-if="scope.row.__editing"
                               v-model="scope.row.thickness"
                               :min="0"
                               :step="1"
@@ -1301,7 +1346,7 @@
                           prop="taxInclusiveUnitPrice"
                           min-width="105">
            <template #default="scope">
              <el-input-number v-if="scope.row.__editing"
              <el-input-number :controls="false" v-if="scope.row.__editing"
                               :step="0.01"
                               :min="0"
                               :precision="2"
@@ -1318,8 +1363,7 @@
                           prop="width"
                           min-width="85">
            <template #default="scope">
              <el-input-number v-if="scope.row.__editing"
                               controls-position="right"
              <el-input-number :controls="false" v-if="scope.row.__editing"
                               v-model="scope.row.width"
                               :min="0"
                               :step="1"
@@ -1337,8 +1381,7 @@
                           prop="height"
                           min-width="85">
            <template #default="scope">
              <el-input-number v-if="scope.row.__editing"
                               controls-position="right"
              <el-input-number :controls="false" v-if="scope.row.__editing"
                               v-model="scope.row.height"
                               :min="0"
                               :step="1"
@@ -1356,8 +1399,7 @@
                           prop="quantity"
                           min-width="85">
            <template #default="scope">
              <el-input-number v-if="scope.row.__editing"
                               controls-position="right"
              <el-input-number :controls="false" v-if="scope.row.__editing"
                               v-model="scope.row.quantity"
                               :step="1"
                               :min="0"
@@ -1375,8 +1417,7 @@
                           prop="settlePieceArea"
                           min-width="120">
            <template #default="scope">
              <el-input-number v-if="scope.row.__editing"
                               controls-position="right"
              <el-input-number :controls="false" v-if="scope.row.__editing"
                               v-model="scope.row.settlePieceArea"
                               :min="0"
                               :step="1"
@@ -1393,8 +1434,7 @@
                           prop="actualTotalArea"
                           min-width="110">
            <template #default="scope">
              <el-input-number v-if="scope.row.__editing"
                               controls-position="right"
              <el-input-number :controls="false" v-if="scope.row.__editing"
                               v-model="scope.row.actualTotalArea"
                               :min="0"
                               :step="1"
@@ -1571,7 +1611,7 @@
                              style="max-width: 170px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;">
                        {{ item.processName }}
                      </el-tag>
                      <el-input-number v-model="item.quantity"
                      <el-input-number :controls="false" v-model="item.quantity"
                                       :min="0"
                                       :step="1"
                                       :precision="0"
@@ -1683,7 +1723,7 @@
                              style="max-width: 170px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;">
                        {{ item.processName }}
                      </el-tag>
                      <el-input-number v-model="item.quantity"
                      <el-input-number :controls="false" v-model="item.quantity"
                                       :min="0"
                                       :step="1"
                                       :precision="0"
@@ -1750,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
@@ -1889,7 +1929,7 @@
          <el-col :span="8">
            <el-form-item label="厚度:"
                          prop="thickness">
              <el-input-number v-model="productForm.thickness"
              <el-input-number :controls="false" v-model="productForm.thickness"
                               :min="0"
                               :step="0.000000000000001"
                               :precision="15"
@@ -1904,7 +1944,7 @@
          <el-col :span="8">
            <el-form-item label="含税单价(元):"
                          prop="taxInclusiveUnitPrice">
              <el-input-number :step="0.01"
              <el-input-number :controls="false" :step="0.01"
                               :min="0"
                               v-model="productForm.taxInclusiveUnitPrice"
                               style="width: 100%"
@@ -1938,7 +1978,7 @@
          <el-col :span="8">
            <el-form-item label="数量:"
                          prop="quantity">
              <el-input-number :step="0.1"
              <el-input-number :controls="false" :step="0.1"
                               :min="0"
                               v-model="productForm.quantity"
                               placeholder="请输入"
@@ -1989,7 +2029,7 @@
          <el-col :span="8">
            <el-form-item label="宽(mm):"
                          prop="width">
              <el-input-number v-model="productForm.width"
              <el-input-number :controls="false" v-model="productForm.width"
                               :min="0"
                               :step="1"
                               :precision="2"
@@ -2002,7 +2042,7 @@
          <el-col :span="8">
            <el-form-item label="高(mm):"
                          prop="height">
              <el-input-number v-model="productForm.height"
              <el-input-number :controls="false" v-model="productForm.height"
                               :min="0"
                               :step="1"
                               :precision="2"
@@ -2015,7 +2055,7 @@
          <el-col :span="8">
            <el-form-item label="周长(cm):"
                          prop="perimeter">
              <el-input-number v-model="productForm.perimeter"
              <el-input-number :controls="false" v-model="productForm.perimeter"
                               :min="0"
                               :step="0.01"
                               :precision="2"
@@ -2031,7 +2071,7 @@
          <el-col :span="8">
            <el-form-item label="实际单片面积(㎡):"
                          prop="actualPieceArea">
              <el-input-number v-model="productForm.actualPieceArea"
              <el-input-number :controls="false" v-model="productForm.actualPieceArea"
                               :min="0"
                               :step="0.0001"
                               :precision="4"
@@ -2044,7 +2084,7 @@
          <el-col :span="8">
            <el-form-item label="实际总面积(㎡):"
                          prop="actualTotalArea">
              <el-input-number v-model="productForm.actualTotalArea"
              <el-input-number :controls="false" v-model="productForm.actualTotalArea"
                               :min="0"
                               :step="0.0001"
                               :precision="4"
@@ -2056,7 +2096,7 @@
          <el-col :span="8">
            <el-form-item label="结算单片面积(㎡):"
                          prop="settlePieceArea">
              <el-input-number v-model="productForm.settlePieceArea"
              <el-input-number :controls="false" v-model="productForm.settlePieceArea"
                               :min="0"
                               :step="0.0001"
                               :precision="4"
@@ -2069,7 +2109,7 @@
          <el-col :span="8">
            <el-form-item label="结算总面积(㎡):"
                          prop="settleTotalArea">
              <el-input-number v-model="productForm.settleTotalArea"
              <el-input-number :controls="false" v-model="productForm.settleTotalArea"
                               :min="0"
                               :step="0.0001"
                               :precision="4"
@@ -2081,7 +2121,7 @@
          <el-col :span="8">
            <el-form-item label="结算总面积(㎡):"
                          prop="settleTotalArea">
              <el-input-number v-model="productForm.settleTotalArea"
              <el-input-number :controls="false" v-model="productForm.settleTotalArea"
                               :min="0"
                               :step="0.0001"
                               :precision="4"
@@ -2164,7 +2204,7 @@
                      </el-tag>
                    </div>
                    <div style="flex: 1;">
                      <el-input-number v-model="item.quantity"
                      <el-input-number :controls="false" v-model="item.quantity"
                                       :min="0"
                                       :step="1"
                                       :precision="0"
@@ -2484,6 +2524,7 @@
  import { ElMessageBox, ElMessage } from "element-plus";
  import { ArrowDown, WarningFilled } from "@element-plus/icons-vue";
  import useUserStore from "@/store/modules/user";
  import useAppStore from "@/store/modules/app";
  import { approveUserList } from "@/api/collaborativeApproval/approvalProcess.js";
  import { userListNoPage } from "@/api/system/user.js";
  import FileListDialog from "@/components/Dialog/FileListDialog.vue";
@@ -2491,6 +2532,7 @@
  import OtherAmountMaintenanceButton from "./components/OtherAmountMaintenanceButton.vue";
  import ProcessFlowMaintenanceButton from "./components/ProcessFlowMaintenanceButton.vue";
  import ProcessFlowConfigSelectDialog from "./components/ProcessFlowConfigSelectDialog.vue";
  import ReverseAuditHistory from "../reverseAuditHistory/index.vue";
  import { getQuotationList } from "@/api/salesManagement/salesQuotation.js";
  import {
    ledgerListPage,
@@ -2512,7 +2554,6 @@
    getSalesLabel,
    salesStock,
    counterReview,
    markOrderCompleted,
    incrementPrintCount,
  } from "@/api/salesManagement/salesLedger.js";
  import { modelList, productTreeList } from "@/api/basicData/product.js";
@@ -2544,15 +2585,17 @@
  const tableLoading = ref(false);
  const page = reactive({
    current: 1,
    size: 100,
    size: 50,
  });
  const total = ref(0);
  const fileList = ref([]);
  const processRouteExportDateRange = ref([]);
  // 工艺路线配置选择弹窗(绑定到台账产品)
  const processFlowSelectDialogVisible = ref(false);
  const processFlowSelectLedgerRow = ref(null);
  const processFlowSelectDefaultRouteId = ref(null);
  const processFlowSelectDefaultRecordList = ref([]);
  const processFlowSelectBoundRouteId = ref(null);
  const processFlowSelectBoundRouteName = ref("");
@@ -2588,6 +2631,28 @@
      ? "编辑完成后将自动返回销售台账列表"
      : "新增完成后将自动返回销售台账列表"
  );
  const appStore = useAppStore();
  watch(isFormPageMode, (val) => {
    if (val) {
      appStore.closeSideBar({ withoutAnimation: false });
    } else {
      if (!appStore.sidebar.opened) {
        appStore.toggleSideBar(false);
      }
    }
  });
  onMounted(() => {
    if (isFormPageMode.value) {
      appStore.closeSideBar({ withoutAnimation: false });
    }
  });
  import { onUnmounted } from "vue";
  onUnmounted(() => {
    if (!appStore.sidebar.opened) {
      appStore.toggleSideBar(false);
    }
  });
  const sanitizeLedgerQrFilename = s =>
    String(s)
@@ -2700,8 +2765,7 @@
  // 用户信息表单弹框数据
  const operationType = ref("");
  const dialogFormVisible = ref(false);
  // 已完成订单标记:view 模式但附件上传仍可用
  const isCompletedOrder = ref(false);
  // 已审核订单编辑模式:只能修改单价,其他字段禁用
  const isReviewedEdit = ref(false);
  const data = reactive({
@@ -2714,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: "",
@@ -2737,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("");
@@ -2931,12 +2985,19 @@
  });
  const getPinnedProductPrefill = async () => {
    if (!pinnedProductTemplate.value) return {};
    await getProductOptions();
    if (!pinnedProductTemplate.value) {
      const models = await modelList({});
      modelOptions.value = models || [];
      return {};
    }
    if (pinnedProductTemplate.value.__productCategoryId) {
      const models = await modelList({
        id: pinnedProductTemplate.value.__productCategoryId,
      });
      modelOptions.value = models || [];
    } else {
      const models = await modelList({});
      modelOptions.value = models || [];
    }
    return { ...pinnedProductTemplate.value };
@@ -3019,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(
@@ -3101,7 +3162,7 @@
    if (operationType.value === "view") return;
    if (!row) return;
    if (isProductShipped(row)) {
      proxy.$modal.msgWarning("已发货或审核通过的产品不能编辑");
      proxy.$modal.msgWarning("已出库或审核通过的产品不能编辑");
      return;
    }
    if (!discardPlaceholderRowIfPristine()) return;
@@ -3203,7 +3264,7 @@
    if (operationType.value === "view") return;
    if (!row) return;
    if (isProductShipped(row)) {
      proxy.$modal.msgWarning("已发货或审核通过的产品不能编辑");
      proxy.$modal.msgWarning("已出库或审核通过的产品不能编辑");
      return;
    }
    // 确保 productForm 指向当前行,以复用计算逻辑
@@ -3300,7 +3361,7 @@
    if (!row) return;
    if (operationType.value === "view") return;
    if (isProductShipped(row)) {
      proxy.$modal.msgWarning("已发货或审核通过的产品不能编辑");
      proxy.$modal.msgWarning("已出库或审核通过的产品不能编辑");
      return;
    }
    ensureProductRowDefaults(row);
@@ -3350,7 +3411,7 @@
    if (!row) return;
    if (operationType.value === "view") return;
    if (isProductShipped(row)) {
      proxy.$modal.msgWarning("已发货或审核通过的产品不能编辑");
      proxy.$modal.msgWarning("已出库或审核通过的产品不能编辑");
      return;
    }
    ensureProductRowDefaults(row);
@@ -3769,10 +3830,52 @@
    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");
  const salesLedgerStatusTabs = [
    { key: "all", label: "全部" },
    { key: "pendingReview", label: "未审核" },
    { key: "reviewed", label: "已审核" },
    { key: "reverseReviewed", label: "反审核" },
    { key: "stocked", label: "已入库" },
    { key: "delivered", label: "已出库" },
  ];
  const resetStatusFilters = () => {
    searchForm.reviewStatus = undefined;
    searchForm.stockStatus = undefined;
    searchForm.deliveryStatus = undefined;
  };
  const handleStatusTabChange = tabKey => {
    activeStatusTab.value = tabKey;
    resetStatusFilters();
    switch (tabKey) {
      case "all":
        break;
      case "pendingReview":
        searchForm.reviewStatus = 0;
        break;
      case "reviewed":
        searchForm.reviewStatus = 1;
        break;
      case "reverseReviewed":
        searchForm.reviewStatus = 2;
        break;
      case "stocked":
        searchForm.stockStatus = 2;
        break;
      case "delivered":
        searchForm.deliveryStatus = 5;
        break;
      default:
        break;
    }
    handleQuery();
  };
  const changeDaterange = value => {
    if (value) {
      searchForm.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
@@ -3784,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);
@@ -3813,9 +3912,6 @@
        return !allUnreviewed;
      case 'print':
        return !allReviewed;
      case 'markCompleted':
        // 只有已审核且未完成的订单才能标记完成
        return !allReviewed || hasCompleted;
      default:
        return false;
    }
@@ -3934,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) => {
@@ -3983,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;
  };
@@ -4003,7 +4071,7 @@
    tableLoading.value = true;
    const { entryDate, ...rest } = searchForm;
    // 将范围日期字段传递给后端
    const params = { ...rest, ...page, reviewStatusList: [0, 1] };
    const params = { ...rest, ...page, reviewStatusList: [0, 1, 2] };
    // 移除录入日期的默认值设置,只保留范围日期字段
    delete params.entryDate;
    // 查询客户名称与新增保持一致:先选 customerId,再映射为 customerName 查询
@@ -4177,6 +4245,7 @@
    processFlowSelectLedgerRow.value = ledgerRow;
    processFlowSelectDefaultRouteId.value = null;
    processFlowSelectDefaultRecordList.value = [];
    processFlowSelectBoundRouteId.value = null;
    processFlowSelectBoundRouteName.value = "";
@@ -4186,25 +4255,29 @@
      const boundId = info?.processRouteId ?? info?.routeId ?? info?.id ?? null;
      const boundName =
        info?.processRouteName ?? info?.routeName ?? info?.name ?? "";
      const recordList = Array.isArray(info?.recordList) ? info.recordList : [];
      processFlowSelectBoundRouteId.value = boundId;
      processFlowSelectBoundRouteName.value = boundName;
      processFlowSelectDefaultRouteId.value = boundId;
      processFlowSelectDefaultRecordList.value = recordList;
    } catch (e) {
      // 查询失败时按未绑定处理,不阻塞弹窗
      processFlowSelectBoundRouteId.value = null;
      processFlowSelectBoundRouteName.value = "";
      processFlowSelectDefaultRouteId.value = null;
      processFlowSelectDefaultRecordList.value = [];
    }
    processFlowSelectDialogVisible.value = true;
  };
  // 绑定工艺路线到当前台账数据
  const handleProcessFlowSelectConfirm = async routeId => {
  const handleProcessFlowSelectConfirm = async payload => {
    const ledgerRow = processFlowSelectLedgerRow.value;
    if (!ledgerRow?.id) return;
    const finalRouteId = routeId ?? null;
    const finalRouteId = payload?.routeId ?? payload ?? null;
    const recordList = Array.isArray(payload?.recordList) ? payload.recordList : [];
    if (!finalRouteId) return;
    const oldRouteId = processFlowSelectBoundRouteId.value;
@@ -4234,6 +4307,7 @@
      await saleProcessBind({
        salesLedgerId: ledgerRow.id,
        processRouteId: finalRouteId,
        recordList,
      });
      proxy?.$modal?.msgSuccess?.("工艺路线绑定成功");
@@ -4316,20 +4390,30 @@
  };
  // 获取tree子数据
  const getModels = value => {
    // 产品大类变化时,重置规格型号与厚度,避免旧值残留
    productForm.value.productModelId = null;
    productForm.value.specificationModel = "";
    productForm.value.thickness = null;
    if (!value) {
      productForm.value.productCategory = "";
      modelOptions.value = [];
      modelList({}).then(res => {
        modelOptions.value = res || [];
      });
      return;
    }
    productForm.value.productCategory = findNodeById(productOptions.value, value);
    modelList({ id: value }).then(res => {
      modelOptions.value = res || [];
      const currentModelId = productForm.value.productModelId;
      if (currentModelId) {
        const isValid = modelOptions.value.some(item => item.id === currentModelId);
        if (!isValid) {
          productForm.value.productModelId = null;
          productForm.value.specificationModel = "";
          productForm.value.thickness = null;
        }
      } else {
        productForm.value.productModelId = null;
        productForm.value.specificationModel = "";
        productForm.value.thickness = null;
      }
    });
  };
  const getProductModel = value => {
@@ -4348,6 +4432,12 @@
        modelThickness === ""
          ? null
          : Number(modelThickness);
      const categoryId = selectedModel?.productId;
      if (categoryId && productForm.value.__productCategoryId !== categoryId) {
        productForm.value.__productCategoryId = categoryId;
        productForm.value.productCategory = findNodeById(productOptions.value, categoryId);
      }
    } else {
      productForm.value.specificationModel = null;
      productForm.value.thickness = null;
@@ -4435,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;
@@ -4479,7 +4569,6 @@
  const initAddFormState = async () => {
    operationType.value = "add";
    isCompletedOrder.value = false;
    isReviewedEdit.value = false;
    form.value = {};
    productData.value = [];
@@ -4497,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 = [];
@@ -4581,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 => {
@@ -4622,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;
  };
@@ -4856,7 +4933,6 @@
      proxy.resetForm("formRef");
    }
    dialogFormVisible.value = false;
    isCompletedOrder.value = false;
    isReviewedEdit.value = false;
    if (!isFormPageMode.value) {
      fileList.value = [];
@@ -4866,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;
    }
@@ -5020,12 +5096,12 @@
      return;
    }
    // 检查是否有已发货或审核通过的产品
    // 检查是否有已出库或审核通过的产品
    const shippedProducts = productSelectedRows.value.filter(row =>
      isProductShipped(row)
    );
    if (shippedProducts.length > 0) {
      proxy.$modal.msgWarning("已发货或审核通过的产品不能删除");
      proxy.$modal.msgWarning("已出库或审核通过的产品不能删除");
      return;
    }
@@ -5158,49 +5234,94 @@
    proxy.$refs["importUploadRef"].submit();
  };
  // 导出
  // 导出(按当前查询条件导出)
  const handleOut = () => {
    if (selectedRows.value.length === 0) {
      proxy.$modal.msgWarning("请至少选择一条数据进行导出");
      return;
    // 构建查询参数(与 getList 保持一致)
    const { entryDate, ...rest } = searchForm;
    const params = { ...rest };
    // 处理录入日期范围
    if (entryDate && entryDate.length === 2) {
      params.entryDateStart = entryDate[0];
      params.entryDateEnd = entryDate[1];
    }
    const hasUnapproved = selectedRows.value.some(
      row => Number(row.reviewStatus) !== 1
    // 处理客户名称查询
    const selectedCustomer = (customerOption.value || []).find(
      item => String(item?.id ?? "") === String(params.customerId ?? "")
    );
    if (hasUnapproved) {
      proxy.$modal.msgWarning("选中的数据中包含未审核项,无法导出");
    if (selectedCustomer?.customerName) {
      params.customerName = String(selectedCustomer.customerName).trim();
    }
    delete params.customerId;
    // 处理产品宽高查询参数
    const widthValue = params.width != null ? String(params.width).trim() : "";
    const heightValue = params.height != null ? String(params.height).trim() : "";
    if (!widthValue) delete params.width;
    if (!heightValue) delete params.height;
    proxy.download("/sales/ledger/exportWithProducts", params, "销售台账.xlsx");
  };
  const exportProcessRouteDialogVisible = ref(false);
  const handleExportProcessRoute = () => {
    if (selectedRows.value.length === 0) {
      proxy?.$modal?.msgWarning?.("请选择要导出的销售台账");
      return;
    }
    ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
      confirmButtonText: "确认",
      cancelButtonText: "取消",
      type: "warning",
    })
      .then(() => {
        proxy.download("/sales/ledger/export", {}, "销售台账.xlsx");
      })
      .catch(() => {
        proxy.$modal.msg("已取消");
      });
    const salesLedgerIds = selectedRows.value
      .map(item => item.id)
      .filter(id => id !== null && id !== undefined && id !== "");
    if (salesLedgerIds.length === 0) {
      proxy?.$modal?.msgWarning?.("请选择要导出的销售台账");
      return;
    }
    exportProcessRouteDialogVisible.value = true;
  };
  /** 判断单个产品是否已发货(根据shippingStatus判断,已发货或审核通过不可编辑和删除) */
  const confirmExportProcessRoute = () => {
    const salesLedgerIds = selectedRows.value
      .map(item => item.id)
      .filter(id => id !== null && id !== undefined && id !== "");
    const params = {
      salesLedgerIds: salesLedgerIds.join(","),
    };
    if (
      Array.isArray(processRouteExportDateRange.value) &&
      processRouteExportDateRange.value.length === 2
    ) {
      params.completedTimeStart = processRouteExportDateRange.value[0];
      params.completedTimeEnd = processRouteExportDateRange.value[1];
    }
    proxy.download(
      "/sales/ledger/exportProcessRoute",
      params,
      "销售台账工艺路线导出.xlsx"
    );
    exportProcessRouteDialogVisible.value = false;
  };
  /** 判断单个产品是否已出库(根据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 === "已出库"
      );
    });
  };
@@ -5716,9 +5837,9 @@
   * @param row 行数据
   */
  const getShippingStatusText = row => {
    // 如果已发货(有发货日期或车牌号),显示"已发货"
    // 如果已出库(有发货日期或车牌号),显示"已出库"
    if (row.shippingDate || row.shippingCarNumber) {
      return "已发货";
      return "已出库";
    }
    // 获取发货状态字段
@@ -5737,7 +5858,7 @@
      审核中: "审核中",
      审核拒绝: "审核拒绝",
      审核通过: "审核通过",
      已发货: "已发货",
      已出库: "已出库",
    };
    return statusTextMap[statusStr] || "待发货";
  };
@@ -5747,7 +5868,7 @@
   * @param row 行数据
   */
  const getShippingStatusType = row => {
    // 如果已发货(有发货日期或车牌号),显示绿色
    // 如果已出库(有发货日期或车牌号),显示绿色
    if (row.shippingDate || row.shippingCarNumber) {
      return "success";
    }
@@ -5768,7 +5889,7 @@
      审核中: "warning",
      审核拒绝: "danger",
      审核通过: "success",
      已发货: "success",
      已出库: "success",
    };
    return typeTextMap[statusStr] || "info";
  };
@@ -5784,7 +5905,7 @@
      return false;
    }
    // 台账级发货状态(deliveryStatus):2审批中、5已发货 时不可再发起本行发货;6部分发货仍可按明细继续发
    // 台账级发货状态(deliveryStatus):2审批中、5已出库 时不可再发起本行发货;6部分发货仍可按明细继续发
    const deliveryStatus = row.deliveryStatus;
    if (
      deliveryStatus !== null &&
@@ -5798,7 +5919,7 @@
    // 获取发货状态
    const shippingStatus = row.shippingStatus;
    // 如果已发货(有发货日期或车牌号),不能再次发货
    // 如果已出库(有发货日期或车牌号),不能再次发货
    if (row.shippingDate || row.shippingCarNumber) {
      return false;
    }
@@ -5848,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;
@@ -5899,7 +6020,7 @@
    );
    if (shippedLedgers.length === selectedRows.value.length) {
      try {
        await ElMessageBox.alert("所选销售台账均已发货,不能再次发货。", "提示", {
        await ElMessageBox.alert("所选销售台账均已出库,不能再次发货。", "提示", {
          type: "warning",
          confirmButtonText: "知道了",
        });
@@ -5911,7 +6032,7 @@
    if (shippedLedgers.length > 0) {
      try {
        await ElMessageBox.alert(
          "选中的销售台账中包含已发货记录,已发货的不能再次发货,系统将仅为未发货台账处理。",
          "选中的销售台账中包含已出库记录,已出库的不能再次发货,系统将仅为未出库台账处理。",
          "提示",
          {
            type: "warning",
@@ -6013,7 +6134,7 @@
    const status = Number(row.deliveryStatus);
    if (![1, 3, 4, 6].includes(status)) {
      proxy.$modal.msgWarning(
        "只有发货状态为未发货、审批不通过、审批通过或部分发货的记录才可以发货"
        "只有发货状态为未出库、审批不通过、审批通过或部分发货的记录才可以发货"
      );
      return;
    }
@@ -6130,7 +6251,7 @@
    currentFactoryName.value = res.user.currentFactoryName;
  };
  onMounted(() => {
    getList();
    handleStatusTabChange(activeStatusTab.value);
    customerList().then(res => {
      customerOption.value = res;
    });
@@ -6180,10 +6301,77 @@
    margin-top: unset;
  }
  .sales-ledger-status-bar {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    padding: 12px 14px;
    margin-bottom: 14px;
    background: linear-gradient(180deg, #f9fbff 0%, #f2f6ff 100%);
    border: 1px solid #dbe6ff;
    border-radius: 12px;
  }
  .sales-ledger-status-tab {
    min-width: 88px;
    height: 34px;
    padding: 0 14px;
    border: 1px solid #d7def0;
    border-radius: 9px;
    background: #fff;
    color: #4b5567;
    font-size: 13px;
    cursor: pointer;
    transition: all 0.18s ease;
  }
  .sales-ledger-status-tab:hover {
    border-color: #8fb3ff;
    color: #1d4ed8;
  }
  .sales-ledger-status-tab.is-active {
    border-color: #1d4ed8;
    background: linear-gradient(135deg, #2f67f6 0%, #1d4ed8 100%);
    color: #fff;
    box-shadow: 0 8px 18px rgba(29, 78, 216, 0.16);
  }
  .actions {
    display: flex;
    justify-content: space-between;
    margin-bottom: 10px;
  }
  .sales-ledger-toolbar {
    align-items: flex-start;
    gap: 14px;
    padding: 10px 12px;
    background: #fff;
    border: 1px solid #e7edf7;
    border-radius: 12px;
  }
  .sales-ledger-toolbar-actions {
    display: flex;
    flex: 1;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 10px;
  }
  .sales-ledger-toolbar-group {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    padding: 4px;
    background: #f7f9fc;
    border: 1px solid #edf1f7;
    border-radius: 10px;
  }
  .sales-ledger-toolbar-group--muted {
    background: #fbfcfe;
  }
  .sales-ledger-page-header {
@@ -6244,7 +6432,7 @@
    :deep(.el-input-number .el-input__wrapper) {
      padding-left: 8px;
      padding-right: 34px;
      padding-right: 8px;
    }
    :deep(.el-input-number),
@@ -6333,9 +6521,20 @@
  }
  @media (max-width: 768px) {
    .sales-ledger-status-tab {
      min-width: unset;
      flex: 1 1 calc(50% - 8px);
    }
    .sales-ledger-toolbar,
    .sales-ledger-page-header {
      flex-direction: column;
      align-items: stretch;
    }
    .sales-ledger-toolbar-actions {
      width: 100%;
      justify-content: flex-start;
    }
    .approver-node-item {
@@ -6363,4 +6562,4 @@
    margin-right: 0;
    margin-bottom: 8px;
  }
</style>
</style>