src/views/salesManagement/salesLedger/index.vue
@@ -1,25 +1,53 @@
<template>
  <div class="app-container">
    <div class="search_form">
      <el-form :model="searchForm" :inline="true">
      <el-form :model="searchForm"
               :inline="true">
        <el-form-item label="客户名称:">
          <el-input v-model="searchForm.customerName" placeholder="请输入" clearable prefix-icon="Search"
            @change="handleQuery" />
          <el-input v-model="searchForm.customerName"
                    placeholder="请输入"
                    clearable
                    prefix-icon="Search"
                    @change="handleQuery" />
        </el-form-item>
        <el-form-item label="销售合同号:">
          <el-input v-model="searchForm.salesContractNo" placeholder="请输入" clearable prefix-icon="Search"
            @change="handleQuery" />
          <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-input v-model="searchForm.projectName"
                    placeholder="请输入"
                    clearable
                    prefix-icon="Search"
                    @change="handleQuery" />
        </el-form-item>
        <el-form-item label="客户类型:">
          <el-select v-model="searchForm.customerType"
                     placeholder="请选择"
                     style="width: 220px"
                     clearable
                     @change="handleQuery">
            <el-option label="对公"
                       value="1" />
            <el-option label="对私"
                       value="2" />
          </el-select>
        </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-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>
          <el-button type="primary" @click="handleQuery"> 搜索 </el-button>
          <el-button type="primary"
                     @click="handleQuery"> 搜索 </el-button>
        </el-form-item>
      </el-form>
    </div>
@@ -27,79 +55,146 @@
      <div class="actions">
        <div></div>
        <div>
          <el-button type="primary" @click="openForm('add')">
          <el-button type="primary"
                     @click="openForm('add')">
            新增台账
          </el-button>
          <el-button type="primary" plain @click="handleImport">导入</el-button>
          <el-button type="primary"
                     plain
                     @click="handleImport">导入</el-button>
          <el-button @click="handleOut">导出</el-button>
          <el-button type="danger" plain @click="handleDelete">删除</el-button>
          <el-button type="primary" plain @click="handlePrint">打印</el-button>
          <el-button type="danger"
                     plain
                     @click="handleDelete">删除</el-button>
          <el-button type="primary"
                     plain
                     @click="handlePrint">打印</el-button>
        </div>
      </div>
      <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange"
        :expand-row-keys="expandedRowKeys" :row-key="(row) => row.id" :row-class-name="tableRowClassName" show-summary style="width: 100%"
        :summary-method="summarizeMainTable" @expand-change="expandChange" height="calc(100vh - 18.5em)">
        <el-table-column align="center" type="selection" width="55" fixed="left"/>
        <el-table-column type="expand" width="60" fixed="left">
      <el-table :data="tableData"
                border
                v-loading="tableLoading"
                @selection-change="handleSelectionChange"
                :expand-row-keys="expandedRowKeys"
                :row-key="(row) => row.id"
                :row-class-name="tableRowClassName"
                show-summary
                style="width: 100%"
                :summary-method="summarizeMainTable"
                @expand-change="expandChange"
                height="calc(100vh - 18.5em)">
        <el-table-column align="center"
                         type="selection"
                         width="55"
                         fixed="left" />
        <el-table-column type="expand"
                         width="60"
                         fixed="left">
          <template #default="props">
            <el-table :data="props.row.children" border show-summary :summary-method="summarizeChildrenTable">
              <el-table-column align="center" label="序号" type="index"/>
              <el-table-column label="产品大类" prop="productCategory" />
              <el-table-column label="规格型号" prop="specificationModel" />
              <el-table-column label="单位" prop="unit" />
                     <el-table-column label="产品状态"
                                              width="100px"
                                              align="center">
            <el-table :data="props.row.children"
                      border
                      show-summary
                      :summary-method="summarizeChildrenTable">
              <el-table-column align="center"
                               label="序号"
                               type="index" />
              <el-table-column label="产品大类"
                               prop="productCategory" />
              <el-table-column label="规格型号"
                               prop="specificationModel" />
              <el-table-column label="单位"
                               prop="unit" />
              <el-table-column label="产品状态"
                               width="100px"
                               align="center">
                <template #default="scope">
                           <el-tag v-if="scope.row.approveStatus === 1 && (!scope.row.shippingDate || !scope.row.shippingCarNumber)"
                                       type="success">充足</el-tag>
                           <el-tag v-else-if="scope.row.approveStatus === 0 && (scope.row.shippingDate || scope.row.shippingCarNumber)"
                                       type="success">已出库</el-tag>
                           <el-tag v-else type="danger">不足</el-tag>
                  <el-tag v-if="scope.row.approveStatus === 1 && (!scope.row.shippingDate || !scope.row.shippingCarNumber)"
                          type="success">充足</el-tag>
                  <el-tag v-else-if="scope.row.approveStatus === 0 && (scope.row.shippingDate || scope.row.shippingCarNumber)"
                          type="success">已出库</el-tag>
                  <el-tag v-else
                          type="danger">不足</el-tag>
                </template>
              </el-table-column>
                     <el-table-column label="发货状态" width="140" align="center">
                        <template #default="scope">
                           <el-tag :type="getShippingStatusType(scope.row)" size="small">
                              {{ getShippingStatusText(scope.row) }}
                           </el-tag>
                        </template>
                     </el-table-column>
                     <el-table-column label="快递公司" prop="expressCompany" show-overflow-tooltip />
                     <el-table-column label="快递单号" prop="expressNumber" show-overflow-tooltip />
              <el-table-column label="发货车牌" minWidth="100px" align="center">
              <el-table-column label="发货状态"
                               width="140"
                               align="center">
                <template #default="scope">
                  <el-tag :type="getShippingStatusType(scope.row)"
                          size="small">
                    {{ getShippingStatusText(scope.row) }}
                  </el-tag>
                </template>
              </el-table-column>
              <el-table-column label="快递公司"
                               prop="expressCompany"
                               show-overflow-tooltip />
              <el-table-column label="快递单号"
                               prop="expressNumber"
                               show-overflow-tooltip />
              <el-table-column label="发货车牌"
                               minWidth="100px"
                               align="center">
                <template #default="scope">
                  <div>
                    <el-tag type="success" v-if="scope.row.shippingCarNumber">{{ scope.row.shippingCarNumber }}</el-tag>
                    <el-tag v-else type="info">-</el-tag>
                    <el-tag type="success"
                            v-if="scope.row.shippingCarNumber">{{ scope.row.shippingCarNumber }}</el-tag>
                    <el-tag v-else
                            type="info">-</el-tag>
                  </div>
                </template>
              </el-table-column>
                     <el-table-column label="发货日期"
                                              minWidth="100px"
                                              align="center">
              <el-table-column label="发货日期"
                               minWidth="100px"
                               align="center">
                <template #default="scope">
                  <div>
                    <div v-if="scope.row.shippingDate">{{ scope.row.shippingDate }}</div>
                              <el-tag v-else
                                          type="info">-</el-tag>
                    <el-tag v-else
                            type="info">-</el-tag>
                  </div>
                </template>
              </el-table-column>
              <el-table-column label="数量" prop="quantity" />
              <el-table-column label="税率(%)" prop="taxRate" />
              <el-table-column label="含税单价(元)" prop="taxInclusiveUnitPrice" :formatter="formattedNumber" />
              <el-table-column label="含税总价(元)" prop="taxInclusiveTotalPrice" :formatter="formattedNumber" />
              <el-table-column label="不含税总价(元)" prop="taxExclusiveTotalPrice" :formatter="formattedNumber" />
            <!--操作-->
              <!-- <el-table-column Width="60px" label="操作" align="center">
              <el-table-column label="数量"
                               prop="quantity" />
              <!-- 对公客户显示的字段 -->
              <template v-if="props.row.customerType =='1'">
                <el-table-column label="税率(%)"
                                 prop="taxRate" />
                <el-table-column label="含税单价(元)"
                                 prop="taxInclusiveUnitPrice"
                                 :formatter="formattedNumber" />
                <el-table-column label="含税总价(元)"
                                 prop="taxInclusiveTotalPrice"
                                 :formatter="formattedNumber" />
                <el-table-column label="不含税总价(元)"
                                 prop="taxExclusiveTotalPrice"
                                 :formatter="formattedNumber" />
              </template>
              <!-- 对私客户显示的字段 -->
              <template v-else-if="props.row.customerType == 2">
                <el-table-column label="单价"
                                 prop="unitPrice"
                                 :formatter="formattedNumber" />
                <el-table-column label="总价"
                                 prop="totalPrice"
                                 :formatter="formattedNumber" />
                <el-table-column label="运费"
                                 prop="freight"
                                 :formatter="formattedNumber" />
                <el-table-column label="含运费单价"
                                 prop="priceWithFreight"
                                 :formatter="formattedNumber" />
              </template>
              <!--操作-->
              <!-- <el-table-column Width="60px"
                               label="操作"
                               align="center">
                <template #default="scope">
                  <el-button
                    link
                    type="primary"
                    :disabled="!canShip(scope.row)"
                    @click="openDeliveryForm(scope.row)">
                  <el-button link
                             type="primary"
                             :disabled="!canShip(scope.row)"
                             @click="openDeliveryForm(scope.row)">
                    发货
                  </el-button>
                </template>
@@ -107,2040 +202,2555 @@
            </el-table>
          </template>
        </el-table-column>
        <el-table-column align="center" label="序号" type="index" width="60" />
        <el-table-column label="销售合同号" prop="salesContractNo" width="180" show-overflow-tooltip />
        <el-table-column label="客户名称" prop="customerName" width="300" show-overflow-tooltip />
        <el-table-column label="业务员" prop="salesman" width="100" show-overflow-tooltip />
        <el-table-column label="项目名称" prop="projectName" width="180" show-overflow-tooltip />
        <el-table-column label="付款方式" prop="paymentMethod" show-overflow-tooltip />
        <el-table-column label="合同金额(元)" prop="contractAmount" width="220" show-overflow-tooltip
          :formatter="formattedNumber" />
        <el-table-column label="录入人" prop="entryPersonName" width="100" show-overflow-tooltip />
        <el-table-column label="录入日期" prop="entryDate" width="120" show-overflow-tooltip />
        <el-table-column label="签订日期" prop="executionDate" width="120" show-overflow-tooltip />
        <el-table-column label="交付日期" prop="deliveryDate" width="120" show-overflow-tooltip />
        <el-table-column label="备注" prop="remarks" width="200" show-overflow-tooltip />
        <el-table-column fixed="right" label="操作" width="130" align="center">
        <el-table-column align="center"
                         label="序号"
                         type="index"
                         width="60" />
        <el-table-column label="销售合同号"
                         prop="salesContractNo"
                         width="180"
                         show-overflow-tooltip />
        <el-table-column label="客户名称"
                         prop="customerName"
                         width="300"
                         show-overflow-tooltip />
        <el-table-column label="客户类型"
                         prop="customerType"
                         width="100">
          <template #default="scope">
            <el-button link type="primary" @click="openForm('edit', scope.row)" :disabled="!scope.row.isEdit">编辑</el-button>
            <el-button link type="primary" @click="downLoadFile(scope.row)">附件</el-button>
            {{scope.row.customerType == 1 ? '对公' : '对私'}}
          </template>
        </el-table-column>
        <el-table-column label="业务员"
                         prop="salesman"
                         width="100"
                         show-overflow-tooltip />
        <el-table-column label="项目名称"
                         prop="projectName"
                         width="180"
                         show-overflow-tooltip />
        <el-table-column label="付款方式"
                         prop="paymentMethod"
                         show-overflow-tooltip />
        <el-table-column label="合同金额(元)"
                         prop="contractAmount"
                         width="220"
                         show-overflow-tooltip
                         :formatter="formattedNumber" />
        <el-table-column label="录入人"
                         prop="entryPersonName"
                         width="100"
                         show-overflow-tooltip />
        <el-table-column label="录入日期"
                         prop="entryDate"
                         width="120"
                         show-overflow-tooltip />
        <el-table-column label="签订日期"
                         prop="executionDate"
                         width="120"
                         show-overflow-tooltip />
        <el-table-column label="交付日期"
                         prop="deliveryDate"
                         width="120"
                         show-overflow-tooltip />
        <el-table-column label="备注"
                         prop="remarks"
                         width="200"
                         show-overflow-tooltip />
        <el-table-column fixed="right"
                         label="操作"
                         width="130"
                         align="center">
          <template #default="scope">
            <el-button link
                       type="primary"
                       @click="openForm('edit', scope.row)"
                       :disabled="!scope.row.isEdit">编辑</el-button>
            <el-button link
                       type="primary"
                       @click="downLoadFile(scope.row)">附件</el-button>
          </template>
        </el-table-column>
      </el-table>
      <pagination v-show="total > 0" :total="total" layout="total, sizes, prev, pager, next, jumper"
        :page="page.current" :limit="page.size" @pagination="paginationChange" />
      <pagination v-show="total > 0"
                  :total="total"
                  layout="total, sizes, prev, pager, next, jumper"
                  :page="page.current"
                  :limit="page.size"
                  @pagination="paginationChange" />
    </div>
    <FormDialog v-model="dialogFormVisible" :title="operationType === 'add' ? '新增销售台账页面' : '编辑销售台账页面'" :width="'70%'"
      :operation-type="operationType" @close="closeDia" @confirm="submitForm" @cancel="closeDia">
      <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
            <!-- 报价单导入入口:放在表单顶部,选择后反显客户/业务员等 -->
            <el-row v-if="operationType === 'add'" style="margin-bottom: 10px;">
               <el-col :span="24" style="text-align: right;">
                  <el-button type="primary" plain @click="openQuotationDialog">
                     从销售报价导入
                  </el-button>
               </el-col>
            </el-row>
    <FormDialog v-model="dialogFormVisible"
                :title="operationType === 'add' ? '新增销售台账页面' : '编辑销售台账页面'"
                :width="'70%'"
                :operation-type="operationType"
                @close="closeDia"
                @confirm="submitForm"
                @cancel="closeDia">
      <el-form :model="form"
               label-width="140px"
               label-position="top"
               :rules="rules"
               ref="formRef">
        <!-- 报价单导入入口:放在表单顶部,选择后反显客户/业务员等 -->
        <el-row v-if="operationType === 'add'"
                style="margin-bottom: 10px;">
          <el-col :span="24"
                  style="text-align: right;">
            <el-button type="primary"
                       plain
                       @click="openQuotationDialog">
              从销售报价导入
            </el-button>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="销售合同号:" prop="salesContractNo">
              <el-input v-model="form.salesContractNo" placeholder="自动生成" clearable disabled />
            <el-form-item label="销售合同号:"
                          prop="salesContractNo">
              <el-input v-model="form.salesContractNo"
                        placeholder="自动生成"
                        clearable
                        disabled />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="业务员:" prop="salesman">
              <el-select v-model="form.salesman" placeholder="请选择" clearable :disabled="operationType === 'view'">
                <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName"
                  :value="item.nickName" />
            <el-form-item label="业务员:"
                          prop="salesman">
              <el-select v-model="form.salesman"
                         placeholder="请选择"
                         clearable
                         :disabled="operationType === 'view'">
                <el-option v-for="item in userList"
                           :key="item.nickName"
                           :label="item.nickName"
                           :value="item.nickName" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="客户名称:" prop="customerId">
              <el-select v-model="form.customerId" placeholder="请选择" clearable :disabled="operationType === 'view'">
                <el-option v-for="item in customerOption" :key="item.id" :label="item.customerName" :value="item.id">
                  {{
                    item.customerName + "——" + item.taxpayerIdentificationNumber
                  }}
            <el-form-item label="客户名称:"
                          prop="customerId">
              <el-select v-model="form.customerId"
                         placeholder="请选择"
                         clearable
                         :disabled="operationType === 'view'"
                         @change="handleCustomerChange">
                <el-option v-for="item in customerOption"
                           :key="item.id"
                           :label="item.customerName"
                           :value="item.id">
                  {{ item.customerName + "——" }}
                  {{item.customerType=="1"?item.taxpayerIdentificationNumber || '无':"对私"}}
                </el-option>
              </el-select>
            </el-form-item>
          </el-col>
               <el-col :span="12">
                  <el-form-item label="项目名称:" prop="projectName">
                     <el-input v-model="form.projectName" placeholder="请输入" clearable :disabled="operationType === 'view'" />
                  </el-form-item>
               </el-col>
        </el-row>
        <el-row :gutter="30">
               <el-col :span="12">
                  <el-form-item label="签订日期:" prop="executionDate">
                     <el-date-picker style="width: 100%" v-model="form.executionDate" value-format="YYYY-MM-DD"
                                             format="YYYY-MM-DD" type="date" placeholder="请选择" clearable :disabled="operationType === 'view'" />
                  </el-form-item>
               </el-col>
               <el-col :span="12">
                  <el-form-item label="付款方式">
                     <el-input v-model="form.paymentMethod" placeholder="请输入" clearable :disabled="operationType === 'view'" />
                  </el-form-item>
               </el-col>
            </el-row>
            <el-row :gutter="30">
               <el-col :span="12">
                  <el-form-item label="录入人:" prop="entryPerson">
                     <el-select v-model="form.entryPerson"
                                     filterable
                                     default-first-option
                                     :reserve-keyword="false" placeholder="请选择" clearable @change="changs">
                        <el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId" />
                     </el-select>
                  </el-form-item>
               </el-col>
               <el-col :span="12">
                  <el-form-item label="录入日期:" prop="entryDate">
                     <el-date-picker style="width: 100%" v-model="form.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD"
                                             type="date" placeholder="请选择" clearable />
                  </el-form-item>
               </el-col>
            </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="交货日期:" prop="entryDate">
              <el-date-picker style="width: 100%" v-model="form.deliveryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD"
                              type="date" placeholder="请选择" clearable />
            <el-form-item label="项目名称:"
                          prop="projectName">
              <el-input v-model="form.projectName"
                        placeholder="请输入"
                        clearable
                        :disabled="operationType === 'view'" />
            </el-form-item>
          </el-col>
        </el-row>
            <el-row>
               <el-form-item label="产品信息:" prop="entryDate">
                  <el-button v-if="operationType !== 'view'" type="primary" @click="openProductForm('add')">添加</el-button>
                  <el-button v-if="operationType !== 'view'" plain type="danger" @click="deleteProduct" >删除</el-button>
               </el-form-item>
            </el-row>
            <el-table :data="productData" border @selection-change="productSelected" show-summary
                           :summary-method="summarizeMainTable">
               <el-table-column align="center" type="selection" width="55" v-if="operationType !== 'view'"
                  :selectable="(row) => !isProductShipped(row)" />
               <el-table-column align="center" label="序号" type="index" width="60" />
               <el-table-column label="产品大类" prop="productCategory" />
               <el-table-column label="规格型号" prop="specificationModel" />
               <el-table-column label="单位" prop="unit" />
               <el-table-column label="数量" prop="quantity" />
               <el-table-column label="税率(%)" prop="taxRate" />
               <el-table-column label="含税单价(元)" prop="taxInclusiveUnitPrice" :formatter="formattedNumber" />
               <el-table-column label="含税总价(元)" prop="taxInclusiveTotalPrice" :formatter="formattedNumber" />
               <el-table-column label="不含税总价(元)" prop="taxExclusiveTotalPrice" :formatter="formattedNumber" />
               <el-table-column fixed="right" label="操作" min-width="60" align="center" v-if="operationType !== 'view'">
                  <template #default="scope">
                     <el-button link type="primary" size="small"
                        :disabled="isProductShipped(scope.row)"
                        @click="openProductForm('edit', scope.row,scope.$index)">编辑</el-button>
                  </template>
               </el-table-column>
            </el-table>
            <el-row :gutter="30">
               <el-col :span="24">
                  <el-form-item label="备注:" prop="remarks">
                     <el-input v-model="form.remarks" placeholder="请输入" clearable type="textarea" :rows="2" :disabled="operationType === 'view'" />
                  </el-form-item>
               </el-col>
            </el-row>
            <el-row :gutter="30">
               <el-col :span="24">
                  <el-form-item label="附件材料:" prop="salesLedgerFiles">
                     <el-upload v-model:file-list="fileList" :action="upload.url" multiple ref="fileUpload" auto-upload
                                     :headers="upload.headers" :before-upload="handleBeforeUpload" :on-error="handleUploadError"
                                     :on-success="handleUploadSuccess" :on-remove="handleRemove">
                        <el-button type="primary" v-if="operationType !== 'view'">上传</el-button>
                        <template #tip 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
                           </div>
                        </template>
                     </el-upload>
                  </el-form-item>
               </el-col>
            </el-row>
         </el-form>
      </FormDialog>
      <!-- 从报价单导入(仅审批通过) -->
      <el-dialog
         v-model="quotationDialogVisible"
         title="选择审批通过的销售报价单"
         width="80%"
         :close-on-click-modal="false"
      >
         <div style="margin-bottom: 12px; display:flex; gap: 12px; align-items:center;">
            <el-input
               v-model="quotationSearchForm.quotationNo"
               placeholder="请输入报价单号"
               clearable
               style="max-width: 260px;"
               @change="fetchQuotationList"
            />
            <el-input
               v-model="quotationSearchForm.customer"
               placeholder="请输入客户名称"
               clearable
               style="max-width: 260px;"
               @change="fetchQuotationList"
            />
            <el-button type="primary" @click="fetchQuotationList">搜索</el-button>
            <el-button @click="resetQuotationSearch">重置</el-button>
         </div>
         <el-table
            :data="quotationList"
            border
            stripe
            v-loading="quotationLoading"
            height="420px"
         >
            <el-table-column align="center" label="序号" type="index" width="60" />
            <el-table-column prop="quotationNo" label="报价单号" width="180" show-overflow-tooltip />
            <el-table-column prop="customer" label="客户名称" min-width="220" show-overflow-tooltip />
            <el-table-column prop="salesperson" label="业务员" width="120" show-overflow-tooltip />
            <el-table-column prop="quotationDate" label="报价日期" width="140" />
            <el-table-column prop="status" label="审批状态" width="120" align="center" />
            <el-table-column prop="totalAmount" label="报价金额(元)" width="160" align="right">
               <template #default="scope">
                  {{ Number(scope.row.totalAmount ?? 0).toFixed(2) }}
               </template>
            </el-table-column>
            <el-table-column fixed="right" label="操作" width="120" align="center">
               <template #default="scope">
                  <el-button type="primary" link @click="applyQuotation(scope.row)">选择</el-button>
               </template>
            </el-table-column>
         </el-table>
         <pagination
            v-show="quotationPage.total > 0"
            :total="quotationPage.total"
            layout="total, sizes, prev, pager, next, jumper"
            :page="quotationPage.current"
            :limit="quotationPage.size"
            @pagination="quotationPaginationChange"
         />
         <template #footer>
            <el-button @click="quotationDialogVisible = false">关闭</el-button>
         </template>
      </el-dialog>
      <FormDialog
         v-model="productFormVisible"
         :title="productOperationType === 'add' ? '新增产品' : '编辑产品'"
         :width="'40%'"
         :operation-type="productOperationType"
         @close="closeProductDia"
         @confirm="submitProduct"
         @cancel="closeProductDia">
         <el-form :model="productForm" label-width="140px" label-position="top" :rules="productRules" ref="productFormRef">
            <el-row :gutter="30">
               <el-col :span="24">
                  <el-form-item label="产品大类:" prop="productCategory">
                     <!-- <el-select v-model="productForm.productCategory" placeholder="请选择" clearable>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="签订日期:"
                          prop="executionDate">
              <el-date-picker style="width: 100%"
                              v-model="form.executionDate"
                              value-format="YYYY-MM-DD"
                              format="YYYY-MM-DD"
                              type="date"
                              placeholder="请选择"
                              clearable
                              :disabled="operationType === 'view'" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="付款方式">
              <el-input v-model="form.paymentMethod"
                        placeholder="请输入"
                        clearable
                        :disabled="operationType === 'view'" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="录入人:"
                          prop="entryPerson">
              <el-select v-model="form.entryPerson"
                         filterable
                         default-first-option
                         :reserve-keyword="false"
                         placeholder="请选择"
                         clearable
                         @change="changs">
                <el-option v-for="item in userList"
                           :key="item.userId"
                           :label="item.nickName"
                           :value="item.userId" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="录入日期:"
                          prop="entryDate">
              <el-date-picker style="width: 100%"
                              v-model="form.entryDate"
                              value-format="YYYY-MM-DD"
                              format="YYYY-MM-DD"
                              type="date"
                              placeholder="请选择"
                              clearable />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="交货日期:"
                          prop="entryDate">
              <el-date-picker style="width: 100%"
                              v-model="form.deliveryDate"
                              value-format="YYYY-MM-DD"
                              format="YYYY-MM-DD"
                              type="date"
                              placeholder="请选择"
                              clearable />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-form-item label="产品信息:"
                        prop="entryDate">
            <el-button v-if="operationType !== 'view' && currentCustomerType"
                       type="primary"
                       @click="openProductForm('add')">添加</el-button>
            <el-button v-if="operationType !== 'view'"
                       plain
                       type="danger"
                       @click="deleteProduct"
                       :disabled="!productData.length">删除</el-button>
          </el-form-item>
        </el-row>
        <el-table :data="productData"
                  border
                  @selection-change="productSelected"
                  show-summary
                  :summary-method="summarizeMainTable">
          <el-table-column align="center"
                           type="selection"
                           width="55"
                           v-if="operationType !== 'view'"
                           :selectable="(row) => !isProductShipped(row)" />
          <el-table-column align="center"
                           label="序号"
                           type="index"
                           width="60" />
          <el-table-column label="产品大类"
                           prop="productCategory" />
          <el-table-column label="规格型号"
                           prop="specificationModel" />
          <el-table-column label="单位"
                           prop="unit" />
          <el-table-column label="数量"
                           prop="quantity" />
          <!-- 对公客户显示的字段 -->
          <template v-if="currentCustomerType == 1">
            <el-table-column label="税率(%)"
                             prop="taxRate" />
            <el-table-column label="含税单价(元)"
                             prop="taxInclusiveUnitPrice"
                             :formatter="formattedNumber" />
            <el-table-column label="含税总价(元)"
                             prop="taxInclusiveTotalPrice"
                             :formatter="formattedNumber" />
            <el-table-column label="不含税总价(元)"
                             prop="taxExclusiveTotalPrice"
                             :formatter="formattedNumber" />
          </template>
          <!-- 对私客户显示的字段 -->
          <template v-else-if="currentCustomerType == 2">
            <el-table-column label="单价"
                             prop="unitPrice"
                             :formatter="formattedNumber" />
            <el-table-column label="总价"
                             prop="totalPrice"
                             :formatter="formattedNumber" />
            <el-table-column label="运费"
                             prop="freight"
                             :formatter="formattedNumber" />
            <el-table-column label="含运费单价"
                             prop="priceWithFreight"
                             :formatter="formattedNumber" />
          </template>
          <el-table-column fixed="right"
                           label="操作"
                           min-width="60"
                           align="center"
                           v-if="operationType !== 'view'">
            <template #default="scope">
              <el-button link
                         type="primary"
                         size="small"
                         :disabled="isProductShipped(scope.row)"
                         @click="openProductForm('edit', scope.row,scope.$index)">编辑</el-button>
            </template>
          </el-table-column>
        </el-table>
        <el-row :gutter="30">
          <el-col :span="24">
            <el-form-item label="备注:"
                          prop="remarks">
              <el-input v-model="form.remarks"
                        placeholder="请输入"
                        clearable
                        type="textarea"
                        :rows="2"
                        :disabled="operationType === 'view'" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="24">
            <el-form-item label="附件材料:"
                          prop="salesLedgerFiles">
              <el-upload v-model:file-list="fileList"
                         :action="upload.url"
                         multiple
                         ref="fileUpload"
                         auto-upload
                         :headers="upload.headers"
                         :before-upload="handleBeforeUpload"
                         :on-error="handleUploadError"
                         :on-success="handleUploadSuccess"
                         :on-remove="handleRemove">
                <el-button type="primary"
                           v-if="operationType !== 'view'">上传</el-button>
                <template #tip
                          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
                  </div>
                </template>
              </el-upload>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
    </FormDialog>
    <!-- 从报价单导入(仅审批通过) -->
    <el-dialog v-model="quotationDialogVisible"
               title="选择审批通过的销售报价单"
               width="80%"
               :close-on-click-modal="false">
      <div style="margin-bottom: 12px; display:flex; gap: 12px; align-items:center;">
        <el-input v-model="quotationSearchForm.quotationNo"
                  placeholder="请输入报价单号"
                  clearable
                  style="max-width: 260px;"
                  @change="fetchQuotationList" />
        <el-input v-model="quotationSearchForm.customer"
                  placeholder="请输入客户名称"
                  clearable
                  style="max-width: 260px;"
                  @change="fetchQuotationList" />
        <el-button type="primary"
                   @click="fetchQuotationList">搜索</el-button>
        <el-button @click="resetQuotationSearch">重置</el-button>
      </div>
      <el-table :data="quotationList"
                border
                stripe
                v-loading="quotationLoading"
                height="420px">
        <el-table-column align="center"
                         label="序号"
                         type="index"
                         width="60" />
        <el-table-column prop="quotationNo"
                         label="报价单号"
                         width="180"
                         show-overflow-tooltip />
        <el-table-column prop="customer"
                         label="客户名称"
                         min-width="220"
                         show-overflow-tooltip />
        <el-table-column prop="salesperson"
                         label="业务员"
                         width="120"
                         show-overflow-tooltip />
        <el-table-column prop="quotationDate"
                         label="报价日期"
                         width="140" />
        <el-table-column prop="status"
                         label="审批状态"
                         width="120"
                         align="center" />
        <el-table-column prop="totalAmount"
                         label="报价金额(元)"
                         width="160"
                         align="right">
          <template #default="scope">
            {{ Number(scope.row.totalAmount ?? 0).toFixed(2) }}
          </template>
        </el-table-column>
        <el-table-column fixed="right"
                         label="操作"
                         width="120"
                         align="center">
          <template #default="scope">
            <el-button type="primary"
                       link
                       @click="applyQuotation(scope.row)">选择</el-button>
          </template>
        </el-table-column>
      </el-table>
      <pagination v-show="quotationPage.total > 0"
                  :total="quotationPage.total"
                  layout="total, sizes, prev, pager, next, jumper"
                  :page="quotationPage.current"
                  :limit="quotationPage.size"
                  @pagination="quotationPaginationChange" />
      <template #footer>
        <el-button @click="quotationDialogVisible = false">关闭</el-button>
      </template>
    </el-dialog>
    <FormDialog v-model="productFormVisible"
                :title="productOperationType === 'add' ? '新增产品' : '编辑产品'"
                :width="'40%'"
                :operation-type="productOperationType"
                @close="closeProductDia"
                @confirm="submitProduct"
                @cancel="closeProductDia">
      <el-form :model="productForm"
               label-width="140px"
               label-position="top"
               :rules="productRules"
               ref="productFormRef">
        <el-row :gutter="30">
          <el-col :span="24">
            <el-form-item label="产品大类:"
                          prop="productCategory">
              <!-- <el-select v-model="productForm.productCategory" placeholder="请选择" clearable>
                        <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName" :value="item.nickName"/>
                     </el-select> -->
                     <el-tree-select v-model="productForm.productCategory" placeholder="请选择" clearable check-strictly
                                             @change="getModels" :data="productOptions" :render-after-expand="false" style="width: 100%" />
                  </el-form-item>
               </el-col>
            </el-row>
            <el-row :gutter="30">
               <el-col :span="24">
                  <el-form-item label="规格型号:" prop="productModelId">
                     <el-select v-model="productForm.productModelId" placeholder="请选择" clearable @change="getProductModel" filterable>
                        <el-option v-for="item in modelOptions" :key="item.id" :label="item.model" :value="item.id" />
                     </el-select>
                  </el-form-item>
               </el-col>
            </el-row>
            <el-row :gutter="30">
               <el-col :span="12">
                  <el-form-item label="单位:" prop="unit">
                     <el-input v-model="productForm.unit" placeholder="请输入" clearable />
                  </el-form-item>
               </el-col>
               <el-col :span="12">
                  <el-form-item label="税率(%):" prop="taxRate">
                     <el-select v-model="productForm.taxRate" placeholder="请选择" clearable @change="calculateFromTaxRate">
                        <el-option label="1" value="1" />
                        <el-option label="6" value="6" />
                        <el-option label="13" value="13" />
                     </el-select>
                  </el-form-item>
               </el-col>
            </el-row>
            <el-row :gutter="30">
               <el-col :span="12">
                  <el-form-item label="含税单价(元):" prop="taxInclusiveUnitPrice">
                     <el-input-number :step="0.01" :min="0" v-model="productForm.taxInclusiveUnitPrice" style="width: 100%"
                                              :precision="2"
                                              placeholder="请输入" clearable @change="calculateFromUnitPrice" />
                  </el-form-item>
               </el-col>
               <el-col :span="12">
                  <el-form-item label="数量:" prop="quantity">
                     <el-input-number  :step="0.1" :min="0" v-model="productForm.quantity" placeholder="请输入" clearable
                                                :precision="2"
                                                @change="calculateFromQuantity" style="width: 100%" />
                  </el-form-item>
               </el-col>
            </el-row>
            <el-row :gutter="30">
               <el-col :span="12">
                  <el-form-item label="含税总价(元):" prop="taxInclusiveTotalPrice">
                     <el-input v-model="productForm.taxInclusiveTotalPrice" placeholder="请输入" clearable @change="calculateFromTotalPrice" />
                  </el-form-item>
               </el-col>
               <el-col :span="12">
                  <el-form-item label="不含税总价(元):" prop="taxExclusiveTotalPrice">
                     <el-input v-model="productForm.taxExclusiveTotalPrice" placeholder="请输入" clearable @change="calculateFromExclusiveTotalPrice" />
                  </el-form-item>
               </el-col>
            </el-row>
            <el-row :gutter="30">
               <el-col :span="12">
                  <el-form-item label="发票类型:" prop="invoiceType">
                     <el-select v-model="productForm.invoiceType" placeholder="请选择" clearable>
                        <el-option label="增普票" value="增普票" />
                        <el-option label="增专票" value="增专票" />
                     </el-select>
                  </el-form-item>
               </el-col>
            </el-row>
         </el-form>
      </FormDialog>
      <!-- 导入弹窗 -->
      <FormDialog
         v-model="importUpload.open"
         :title="importUpload.title"
         :width="'600px'"
         @close="importUpload.open = false"
         @confirm="submitImportFile"
         @cancel="importUpload.open = false"
      >
         <el-upload
            ref="importUploadRef"
            :limit="1"
            accept=".xlsx,.xls"
            :action="importUpload.url"
            :headers="importUpload.headers"
            :before-upload="importUpload.beforeUpload"
            :on-success="importUpload.onSuccess"
            :on-error="importUpload.onError"
            :on-progress="importUpload.onProgress"
            :on-change="importUpload.onChange"
            :auto-upload="false"
            drag
         >
            <i class="el-icon-upload"></i>
            <div class="el-upload__text">
               将文件拖到此处,或<em>点击上传</em>
            </div>
            <template #tip>
               <div class="el-upload__tip">
                  仅支持 xls/xlsx,大小不超过 10MB。
                  <el-button link type="primary" @click="downloadTemplate">下载导入模板</el-button>
               </div>
            </template>
         </el-upload>
      </FormDialog>
      <!-- 附件列表弹窗 -->
      <FileListDialog
         ref="fileListRef"
         v-model="fileListDialogVisible"
         title="附件列表"
      />
      <!-- 打印预览弹窗 -->
      <el-dialog
         v-model="printPreviewVisible"
         title="打印预览"
         width="90%"
         :close-on-click-modal="false"
         class="print-preview-dialog"
      >
         <div class="print-preview-container">
            <div class="print-preview-header">
               <el-button type="primary" @click="executePrint">执行打印</el-button>
               <el-button @click="printPreviewVisible = false">关闭预览</el-button>
            </div>
            <div class="print-preview-content">
               <div v-if="printData.length === 0" style="text-align: center; padding: 50px; color: #999;">
                  暂无打印数据
               </div>
               <div v-else style="text-align: center; padding: 10px; color: #666; font-size: 14px; background: #e8f4fd; margin-bottom: 10px;">
                  共 {{ printData.length }} 条数据待打印
               </div>
               <div v-for="(item, index) in printData" :key="index" class="print-page">
                  <div class="delivery-note">
                     <div class="header">
                        <div class="document-title">零售发货单</div>
                     </div>
                     <div class="info-section">
                        <div class="info-row">
                           <div>
                              <span class="label">发货日期:</span>
                              <span class="value">{{ formatDate(item.createTime) }}</span>
                           </div>
                           <div>
                              <span class="label">发货车牌号:</span>
                              <span class="value">{{ item.shippingCarNumber }}</span>
                           </div>
                        </div>
                        <div class="info-row">
                           <div>
                              <span class="label">客户名称:</span>
                              <span class="value">{{ item.customerName }}</span>
                           </div>
                           <span class="label">单号:</span>
                           <span class="value">{{ item.salesContractNo }}</span>
                        </div>
                     </div>
                     <div class="table-section">
                        <table class="product-table">
                           <thead>
                           <tr>
                              <th>产品名称</th>
                              <th>规格型号</th>
                              <th>单位</th>
                              <th>单价</th>
                              <th>零售数量</th>
                              <th>零售金额</th>
                           </tr>
                           </thead>
                           <tbody>
                           <tr v-for="product in item.products" :key="product.id">
                              <td>{{ product.productCategory || '' }}</td>
                              <td>{{ product.specificationModel || '' }}</td>
                              <td>{{ product.unit || '' }}</td>
                              <td>{{ product.taxInclusiveUnitPrice || '0' }}</td>
                              <td>{{ product.quantity || '0' }}</td>
                              <td>{{ product.taxInclusiveTotalPrice || '0' }}</td>
                           </tr>
                           <tr v-if="!item.products || item.products.length === 0">
                              <td colspan="6" style="text-align: center; color: #999;">暂无产品数据</td>
                           </tr>
                           </tbody>
                           <tfoot>
                           <tr>
                              <td class="label">合计</td>
                              <td class="total-value"></td>
                              <td class="total-value"></td>
                              <td class="total-value"></td>
                              <td class="total-value">{{ getTotalQuantity(item.products) }}</td>
                              <td class="total-value">{{ getTotalAmount(item.products) }}</td>
                           </tr>
                           </tfoot>
                        </table>
                     </div>
                     <div class="footer-section">
                        <div class="footer-row">
                           <div class="footer-item">
                              <span class="label">收货电话:</span>
                              <span class="value"></span>
                           </div>
                           <div class="footer-item">
                              <span class="label">收货人:</span>
                              <span class="value"></span>
                           </div>
                           <div class="footer-item address-item">
                              <span class="label">收货地址:</span>
                              <span class="value address-value"></span>
                           </div>
                        </div>
                        <div class="footer-row">
                           <div class="footer-item">
                              <span class="label">操作员:</span>
                              <span class="value">{{ userStore.nickName || '撕开前' }}</span>
                           </div>
                           <div class="footer-item">
                              <span class="label">打印日期:</span>
                              <span class="value">{{ formatDateTime(new Date()) }}</span>
                           </div>
                        </div>
                     </div>
                  </div>
               </div>
            </div>
         </div>
      </el-dialog>
      <!-- 发货弹框 -->
      <el-dialog
         v-model="deliveryFormVisible"
         title="发货信息"
      width="40%"
         @close="closeDeliveryDia"
      >
         <el-form :model="deliveryForm" label-width="120px" label-position="top" :rules="deliveryRules" ref="deliveryFormRef">
            <el-row :gutter="30">
               <el-col :span="24">
                  <el-form-item label="发货类型:" prop="type">
                     <el-select
                        v-model="deliveryForm.type"
                        placeholder="请选择发货类型"
                        style="width: 100%"
                     >
                        <el-option label="货车" value="货车" />
                        <el-option label="快递" value="快递" />
                     </el-select>
                  </el-form-item>
               </el-col>
            </el-row>
              <el-tree-select v-model="productForm.productCategory"
                              placeholder="请选择"
                              clearable
                              check-strictly
                              @change="getModels"
                              :data="productOptions"
                              :render-after-expand="false"
                              style="width: 100%" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="24">
            <el-form-item label="规格型号:"
                          prop="productModelId">
              <el-select v-model="productForm.productModelId"
                         placeholder="请选择"
                         clearable
                         @change="getProductModel"
                         filterable>
                <el-option v-for="item in modelOptions"
                           :key="item.id"
                           :label="item.model"
                           :value="item.id" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="单位:"
                          prop="unit">
              <el-input v-model="productForm.unit"
                        placeholder="请输入"
                        clearable />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="数量:"
                          prop="quantity">
              <el-input-number :step="0.1"
                               :min="0"
                               v-model="productForm.quantity"
                               placeholder="请输入"
                               clearable
                               :precision="2"
                               @change="calculateFromQuantity"
                               style="width: 100%" />
            </el-form-item>
          </el-col>
          <!-- <el-col :span="12">
            <el-form-item label="税率(%):"
                          prop="taxRate">
              <el-select v-model="productForm.taxRate"
                         placeholder="请选择"
                         clearable
                         @change="calculateFromTaxRate">
                <el-option label="1"
                           value="1" />
                <el-option label="6"
                           value="6" />
                <el-option label="13"
                           value="13" />
              </el-select>
            </el-form-item>
          </el-col> -->
        </el-row>
        <el-row :gutter="30">
        </el-row>
        <!-- 对公客户显示的字段 -->
        <template v-if="currentCustomerType == 1">
          <el-row :gutter="30">
            <el-col :span="12">
              <el-form-item label="税率(%):"
                            prop="taxRate">
                <el-select v-model="productForm.taxRate"
                           placeholder="请选择"
                           clearable
                           @change="calculateFromTaxRate">
                  <el-option label="1"
                             value="1" />
                  <el-option label="6"
                             value="6" />
                  <el-option label="13"
                             value="13" />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="含税单价(元):"
                            prop="taxInclusiveUnitPrice">
                <el-input-number :step="0.01"
                                 :min="0"
                                 v-model="productForm.taxInclusiveUnitPrice"
                                 style="width: 100%"
                                 :precision="2"
                                 placeholder="请输入"
                                 clearable
                                 @change="calculateFromUnitPrice" />
              </el-form-item>
            </el-col>
          </el-row>
          <el-row :gutter="30">
            <el-col :span="12">
              <el-form-item label="含税总价(元):"
                            prop="taxInclusiveTotalPrice">
                <el-input v-model="productForm.taxInclusiveTotalPrice"
                          placeholder="请输入"
                          clearable
                          @change="calculateFromTotalPrice" />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="不含税总价(元):"
                            prop="taxExclusiveTotalPrice">
                <el-input v-model="productForm.taxExclusiveTotalPrice"
                          placeholder="请输入"
                          clearable
                          @change="calculateFromExclusiveTotalPrice" />
              </el-form-item>
            </el-col>
          </el-row>
          <el-row :gutter="30">
            <el-col :span="12">
              <el-form-item label="发票类型:"
                            prop="invoiceType">
                <el-select v-model="productForm.invoiceType"
                           placeholder="请选择"
                           clearable>
                  <el-option label="增普票"
                             value="增普票" />
                  <el-option label="增专票"
                             value="增专票" />
                </el-select>
              </el-form-item>
            </el-col>
          </el-row>
        </template>
        <!-- 对私客户显示的字段 -->
        <template v-else-if="currentCustomerType == 2">
          <el-row :gutter="30">
            <el-col :span="12">
              <el-form-item label="单价:"
                            prop="unitPrice">
                <el-input-number :step="0.01"
                                 :min="0"
                                 v-model="productForm.unitPrice"
                                 style="width: 100%"
                                 :precision="2"
                                 placeholder="请输入"
                                 clearable
                                 @change="calculatePrivatePrice" />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="总价:"
                            prop="totalPrice">
                <el-input-number :step="0.01"
                                 :min="0"
                                 v-model="productForm.totalPrice"
                                 style="width: 100%"
                                 :precision="2"
                                 placeholder="请输入"
                                 clearable />
              </el-form-item>
            </el-col>
          </el-row>
          <el-row :gutter="30">
            <el-col :span="12">
              <el-form-item label="运费:"
                            prop="freight">
                <el-input-number :step="0.01"
                                 :min="0"
                                 v-model="productForm.freight"
                                 style="width: 100%"
                                 :precision="2"
                                 placeholder="请输入"
                                 clearable
                                 @change="calculatePrivatePrice" />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="含运费单价:"
                            prop="priceWithFreight">
                <el-input-number :step="0.01"
                                 :min="0"
                                 v-model="productForm.priceWithFreight"
                                 style="width: 100%"
                                 :precision="2"
                                 placeholder="请输入"
                                 clearable
                                 @change="calculatePrivateTotal" />
              </el-form-item>
            </el-col>
          </el-row>
        </template>
      </el-form>
    </FormDialog>
    <!-- 导入弹窗 -->
    <FormDialog v-model="importUpload.open"
                :title="importUpload.title"
                :width="'600px'"
                @close="importUpload.open = false"
                @confirm="submitImportFile"
                @cancel="importUpload.open = false">
      <el-upload ref="importUploadRef"
                 :limit="1"
                 accept=".xlsx,.xls"
                 :action="importUpload.url"
                 :headers="importUpload.headers"
                 :before-upload="importUpload.beforeUpload"
                 :on-success="importUpload.onSuccess"
                 :on-error="importUpload.onError"
                 :on-progress="importUpload.onProgress"
                 :on-change="importUpload.onChange"
                 :auto-upload="false"
                 drag>
        <i class="el-icon-upload"></i>
        <div class="el-upload__text">
          将文件拖到此处,或<em>点击上传</em>
        </div>
        <template #tip>
          <div class="el-upload__tip">
            仅支持 xls/xlsx,大小不超过 10MB。
            <el-button link
                       type="primary"
                       @click="downloadTemplate">下载导入模板</el-button>
          </div>
        </template>
      </el-upload>
    </FormDialog>
    <!-- 附件列表弹窗 -->
    <FileListDialog ref="fileListRef"
                    v-model="fileListDialogVisible"
                    title="附件列表" />
    <!-- 打印预览弹窗 -->
    <el-dialog v-model="printPreviewVisible"
               title="打印预览"
               width="90%"
               :close-on-click-modal="false"
               class="print-preview-dialog">
      <div class="print-preview-container">
        <div class="print-preview-header">
          <el-button type="primary"
                     @click="executePrint">执行打印</el-button>
          <el-button @click="printPreviewVisible = false">关闭预览</el-button>
        </div>
        <div class="print-preview-content">
          <div v-if="printData.length === 0"
               style="text-align: center; padding: 50px; color: #999;">
            暂无打印数据
          </div>
          <div v-else
               style="text-align: center; padding: 10px; color: #666; font-size: 14px; background: #e8f4fd; margin-bottom: 10px;">
            共 {{ printData.length }} 条数据待打印
          </div>
          <div v-for="(item, index) in printData"
               :key="index"
               class="print-page">
            <div class="delivery-note">
              <div class="header">
                <div class="document-title">零售发货单</div>
              </div>
              <div class="info-section">
                <div class="info-row">
                  <div>
                    <span class="label">发货日期:</span>
                    <span class="value">{{ formatDate(item.createTime) }}</span>
                  </div>
                  <div>
                    <span class="label">发货车牌号:</span>
                    <span class="value">{{ item.shippingCarNumber }}</span>
                  </div>
                </div>
                <div class="info-row">
                  <div>
                    <span class="label">客户名称:</span>
                    <span class="value">{{ item.customerName }}</span>
                  </div>
                  <span class="label">单号:</span>
                  <span class="value">{{ item.salesContractNo }}</span>
                </div>
              </div>
              <div class="table-section">
                <table class="product-table">
                  <thead>
                    <tr>
                      <th>产品名称</th>
                      <th>规格型号</th>
                      <th>单位</th>
                      <th>单价</th>
                      <th>零售数量</th>
                      <th>零售金额</th>
                    </tr>
                  </thead>
                  <tbody>
                    <tr v-for="product in item.products"
                        :key="product.id">
                      <td>{{ product.productCategory || '' }}</td>
                      <td>{{ product.specificationModel || '' }}</td>
                      <td>{{ product.unit || '' }}</td>
                      <td>{{ product.taxInclusiveUnitPrice || '0' }}</td>
                      <td>{{ product.quantity || '0' }}</td>
                      <td>{{ product.taxInclusiveTotalPrice || '0' }}</td>
                    </tr>
                    <tr v-if="!item.products || item.products.length === 0">
                      <td colspan="6"
                          style="text-align: center; color: #999;">暂无产品数据</td>
                    </tr>
                  </tbody>
                  <tfoot>
                    <tr>
                      <td class="label">合计</td>
                      <td class="total-value"></td>
                      <td class="total-value"></td>
                      <td class="total-value"></td>
                      <td class="total-value">{{ getTotalQuantity(item.products) }}</td>
                      <td class="total-value">{{ getTotalAmount(item.products) }}</td>
                    </tr>
                  </tfoot>
                </table>
              </div>
              <div class="footer-section">
                <div class="footer-row">
                  <div class="footer-item">
                    <span class="label">收货电话:</span>
                    <span class="value"></span>
                  </div>
                  <div class="footer-item">
                    <span class="label">收货人:</span>
                    <span class="value"></span>
                  </div>
                  <div class="footer-item address-item">
                    <span class="label">收货地址:</span>
                    <span class="value address-value"></span>
                  </div>
                </div>
                <div class="footer-row">
                  <div class="footer-item">
                    <span class="label">操作员:</span>
                    <span class="value">{{ userStore.nickName || '撕开前' }}</span>
                  </div>
                  <div class="footer-item">
                    <span class="label">打印日期:</span>
                    <span class="value">{{ formatDateTime(new Date()) }}</span>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </el-dialog>
    <!-- 发货弹框 -->
    <el-dialog v-model="deliveryFormVisible"
               title="发货信息"
               width="40%"
               @close="closeDeliveryDia">
      <el-form :model="deliveryForm"
               label-width="120px"
               label-position="top"
               :rules="deliveryRules"
               ref="deliveryFormRef">
        <el-row :gutter="30">
          <el-col :span="24">
            <el-form-item label="发货类型:"
                          prop="type">
              <el-select v-model="deliveryForm.type"
                         placeholder="请选择发货类型"
                         style="width: 100%">
                <el-option label="货车"
                           value="货车" />
                <el-option label="快递"
                           value="快递" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <!-- 审批人选择(仿协同审批里的审批人节点选择) -->
        <el-row>
          <el-col :span="24">
            <el-form-item>
              <template #label>
                <span>审批人选择:</span>
                <el-button type="primary" @click="addApproverNode" style="margin-left: 8px;">新增节点</el-button>
                <el-button type="primary"
                           @click="addApproverNode"
                           style="margin-left: 8px;">新增节点</el-button>
              </template>
              <div style="display: flex; align-items: flex-end; flex-wrap: wrap;">
                <div
                  v-for="(node, index) in approverNodes"
                  :key="node.id"
                  style="margin-right: 20px; text-align: center; margin-bottom: 10px;"
                >
                <div v-for="(node, index) in approverNodes"
                     :key="node.id"
                     style="margin-right: 20px; text-align: center; margin-bottom: 10px;">
                  <div>
                    <span>审批人</span>
                    →
                  </div>
                  <el-select
                    v-model="node.userId"
                    placeholder="选择人员"
                    filterable
                    style="width: 140px; margin-bottom: 8px;"
                  >
                    <el-option
                      v-for="user in userList"
                      :key="user.userId"
                      :label="user.nickName"
                      :value="user.userId"
                    />
                  <el-select v-model="node.userId"
                             placeholder="选择人员"
                             filterable
                             style="width: 140px; margin-bottom: 8px;">
                    <el-option v-for="user in userList"
                               :key="user.userId"
                               :label="user.nickName"
                               :value="user.userId" />
                  </el-select>
                  <div>
                    <el-button
                      type="danger"
                      @click="removeApproverNode(index)"
                      v-if="approverNodes.length > 1"
                    >删除</el-button>
                    <el-button type="danger"
                               @click="removeApproverNode(index)"
                               v-if="approverNodes.length > 1">删除</el-button>
                  </div>
                </div>
              </div>
            </el-form-item>
          </el-col>
        </el-row>
         </el-form>
         <template #footer>
            <div class="dialog-footer">
               <el-button type="primary" @click="submitDelivery">确认发货</el-button>
               <el-button @click="closeDeliveryDia">取消</el-button>
            </div>
         </template>
      </el-dialog>
   </div>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary"
                     @click="submitDelivery">确认发货</el-button>
          <el-button @click="closeDeliveryDia">取消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import { getToken } from "@/utils/auth";
import pagination from "@/components/PIMTable/Pagination.vue";
import {onMounted, ref, getCurrentInstance} from "vue";
import { addShippingInfo } from "@/api/salesManagement/deliveryLedger.js";
import { ElMessageBox, ElMessage } from "element-plus";
import { UploadFilled, Download } from "@element-plus/icons-vue";
import useUserStore from "@/store/modules/user";
import { userListNoPage } from "@/api/system/user.js";
import FileListDialog from '@/components/Dialog/FileListDialog.vue';
import FormDialog from '@/components/Dialog/FormDialog.vue';
import { getQuotationList } from "@/api/salesManagement/salesQuotation.js";
import {
   ledgerListPage,
   productList,
   customerList,
   addOrUpdateSalesLedger,
   getSalesLedgerWithProducts,
   delLedger,
   addOrUpdateSalesLedgerProduct,
   delProduct,
   delLedgerFile, getProductInventory,
} from "@/api/salesManagement/salesLedger.js";
import { modelList, productTreeList } from "@/api/basicData/product.js";
import useFormData from "@/hooks/useFormData.js";
import dayjs from "dayjs";
import { getCurrentDate } from "@/utils/index.js";
  import { getToken } from "@/utils/auth";
  import pagination from "@/components/PIMTable/Pagination.vue";
  import { onMounted, ref, getCurrentInstance } from "vue";
  import { addShippingInfo } from "@/api/salesManagement/deliveryLedger.js";
  import { ElMessageBox, ElMessage } from "element-plus";
  import { UploadFilled, Download } from "@element-plus/icons-vue";
  import useUserStore from "@/store/modules/user";
  import { userListNoPage } from "@/api/system/user.js";
  import FileListDialog from "@/components/Dialog/FileListDialog.vue";
  import FormDialog from "@/components/Dialog/FormDialog.vue";
  import { getQuotationList } from "@/api/salesManagement/salesQuotation.js";
  import {
    ledgerListPage,
    productList,
    customerList,
    addOrUpdateSalesLedger,
    getSalesLedgerWithProducts,
    delLedger,
    addOrUpdateSalesLedgerProduct,
    delProduct,
    delLedgerFile,
    getProductInventory,
  } from "@/api/salesManagement/salesLedger.js";
  import { modelList, productTreeList } from "@/api/basicData/product.js";
  import useFormData from "@/hooks/useFormData.js";
  import dayjs from "dayjs";
  import { getCurrentDate } from "@/utils/index.js";
const userStore = useUserStore();
const { proxy } = getCurrentInstance();
const tableData = ref([]);
const productData = ref([]);
const selectedRows = ref([]);
const productSelectedRows = ref([]);
const userList = ref([]);
const customerOption = ref([]);
const productOptions = ref([]);
const modelOptions = ref([]);
const tableLoading = ref(false);
const page = reactive({
   current: 1,
   size: 100,
});
const total = ref(0);
const fileList = ref([]);
  const userStore = useUserStore();
  const { proxy } = getCurrentInstance();
  const tableData = ref([]);
  const productData = ref([]);
  const selectedRows = ref([]);
  const productSelectedRows = ref([]);
  const userList = ref([]);
  const customerOption = ref([]);
  const productOptions = ref([]);
  const modelOptions = ref([]);
  const tableLoading = ref(false);
  const page = reactive({
    current: 1,
    size: 100,
  });
  const total = ref(0);
  const fileList = ref([]);
// 用户信息表单弹框数据
const operationType = ref("");
const dialogFormVisible = ref(false);
const data = reactive({
   searchForm: {
      customerName: "", // 客户名称
      salesContractNo: "", // 销售合同编号
      entryDate: null, // 录入日期
      entryDateStart: undefined,
      entryDateEnd: undefined,
   },
   form: {
      salesContractNo: "",
      salesman: "",
      customerId: "",
      entryPerson: "",
      entryDate: "",
    deliveryDate: "",
      maintenanceTime: "",
      productData: [],
      executionDate: "",
   },
   rules: {
      salesman: [{ required: true, message: "请选择", trigger: "change" }],
      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);
// 产品表单弹框数据
const productFormVisible = ref(false);
const productOperationType = ref("");
const currentId = ref("");
const productFormData = reactive({
   productForm: {
      productCategory: "",
      specificationModel: "",
      unit: "",
      quantity: "",
      taxInclusiveUnitPrice: "",
      taxRate: "",
      taxInclusiveTotalPrice: "",
      taxExclusiveTotalPrice: "",
      invoiceType: "",
   },
   productRules: {
      productCategory: [{ required: true, message: "请选择", trigger: "change" }],
      productModelId: [{ required: true, message: "请选择", trigger: "change" }],
      specificationModel: [
         { required: true, message: "请选择", trigger: "change" },
      ],
      unit: [{ required: true, message: "请输入", trigger: "blur" }],
      quantity: [{ required: true, message: "请输入", trigger: "blur" }],
      taxInclusiveUnitPrice: [
         { required: true, message: "请输入", trigger: "blur" },
      ],
      taxRate: [{ required: true, message: "请选择", trigger: "change" }],
      taxInclusiveTotalPrice: [
         { required: true, message: "请输入", trigger: "blur" },
      ],
      taxExclusiveTotalPrice: [
         { required: true, message: "请输入", trigger: "blur" },
      ],
      invoiceType: [{ required: true, message: "请选择", trigger: "change" }],
   },
});
const { productForm, productRules } = toRefs(productFormData);
// 防止循环计算的标志
const isCalculating = ref(false);
const upload = reactive({
   // 上传的地址
   url: import.meta.env.VITE_APP_BASE_API + "/file/upload",
   // 设置上传的请求头部
   headers: { Authorization: "Bearer " + getToken() },
});
// 打印相关
const printPreviewVisible = ref(false);
const printData = ref([]);
  // 用户信息表单弹框数据
  const operationType = ref("");
  const dialogFormVisible = ref(false);
  const currentCustomerType = ref(""); // 当前客户类型:对公/对私
  const data = reactive({
    searchForm: {
      customerName: "", // 客户名称
      salesContractNo: "", // 销售合同编号
      entryDate: null, // 录入日期
      entryDateStart: undefined,
      entryDateEnd: undefined,
      customerType: "",
    },
    form: {
      salesContractNo: "",
      salesman: "",
      customerId: "",
      entryPerson: "",
      entryDate: "",
      deliveryDate: "",
      maintenanceTime: "",
      productData: [],
      executionDate: "",
    },
    rules: {
      salesman: [{ required: true, message: "请选择", trigger: "change" }],
      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);
  // 产品表单弹框数据
  const productFormVisible = ref(false);
  const productOperationType = ref("");
  const currentId = ref("");
  const productFormData = reactive({
    productForm: {
      productCategory: "",
      specificationModel: "",
      unit: "",
      quantity: "",
      // 对公字段
      taxInclusiveUnitPrice: "",
      taxRate: "",
      taxInclusiveTotalPrice: "",
      taxExclusiveTotalPrice: "",
      invoiceType: "",
      // 对私字段
      unitPrice: "",
      totalPrice: "",
      freight: 0,
      priceWithFreight: "",
    },
    productRules: {
      productCategory: [{ required: true, message: "请选择", trigger: "change" }],
      productModelId: [{ required: true, message: "请选择", trigger: "change" }],
      specificationModel: [
        { required: true, message: "请选择", trigger: "change" },
      ],
      unit: [{ required: true, message: "请输入", trigger: "blur" }],
      quantity: [{ required: true, message: "请输入", trigger: "blur" }],
      // 对公字段验证
      taxInclusiveUnitPrice: [
        { required: true, message: "请输入", trigger: "blur" },
      ],
      taxRate: [{ required: true, message: "请选择", trigger: "change" }],
      taxInclusiveTotalPrice: [
        { required: true, message: "请输入", trigger: "blur" },
      ],
      taxExclusiveTotalPrice: [
        { required: true, message: "请输入", trigger: "blur" },
      ],
      invoiceType: [{ required: true, message: "请选择", trigger: "change" }],
      // 对私字段验证
      unitPrice: [{ required: true, message: "请输入", trigger: "blur" }],
      totalPrice: [{ required: true, message: "请输入", trigger: "blur" }],
      freight: [{ required: true, message: "请输入", trigger: "blur" }],
      priceWithFreight: [{ required: true, message: "请输入", trigger: "blur" }],
    },
  });
  const { productForm, productRules } = toRefs(productFormData);
  // 防止循环计算的标志
  const isCalculating = ref(false);
  const upload = reactive({
    // 上传的地址
    url: import.meta.env.VITE_APP_BASE_API + "/file/upload",
    // 设置上传的请求头部
    headers: { Authorization: "Bearer " + getToken() },
  });
  // 打印相关
  const printPreviewVisible = ref(false);
  const printData = ref([]);
// 报价单导入相关
const quotationDialogVisible = ref(false);
const quotationLoading = ref(false);
const quotationList = ref([]);
const quotationSearchForm = reactive({
   quotationNo: "",
   customer: "",
});
// 报价单弹框分页
const quotationPage = reactive({
   current: 1,
   size: 10,
   total: 0,
});
const selectedQuotation = ref(null);
  // 报价单导入相关
  const quotationDialogVisible = ref(false);
  const quotationLoading = ref(false);
  const quotationList = ref([]);
  const quotationSearchForm = reactive({
    quotationNo: "",
    customer: "",
  });
  // 报价单弹框分页
  const quotationPage = reactive({
    current: 1,
    size: 10,
    total: 0,
  });
  const selectedQuotation = ref(null);
// 发货相关
const deliveryFormVisible = ref(false);
const currentDeliveryRow = ref(null);
const deliveryFormData = reactive({
  deliveryForm: {
    type: "货车", // 货车, 快递
  },
  deliveryRules: {
    type: [
      { required: true, message: "请选择发货类型", trigger: "change" }
    ]
  },
});
const { deliveryForm, deliveryRules } = toRefs(deliveryFormData);
  // 发货相关
  const deliveryFormVisible = ref(false);
  const currentDeliveryRow = ref(null);
  const deliveryFormData = reactive({
    deliveryForm: {
      type: "货车", // 货车, 快递
    },
    deliveryRules: {
      type: [{ required: true, message: "请选择发货类型", trigger: "change" }],
    },
  });
  const { deliveryForm, deliveryRules } = toRefs(deliveryFormData);
// 发货审批人节点(仿协同审批 infoFormDia.vue)
const approverNodes = ref([{ id: 1, userId: null }]);
let nextApproverId = 2;
const addApproverNode = () => {
  approverNodes.value.push({ id: nextApproverId++, userId: null });
};
const removeApproverNode = (index) => {
  approverNodes.value.splice(index, 1);
};
// 导入相关
const importUploadRef = ref(null);
const importUpload = reactive({
   title: "导入销售台账",
   open: false,
   url: import.meta.env.VITE_APP_BASE_API + "/sales/ledger/import",
   headers: { Authorization: "Bearer " + getToken() },
   isUploading: false,
   beforeUpload: (file) => {
      const isExcel = file.name.endsWith('.xlsx') || file.name.endsWith('.xls');
      const isLt10M = file.size / 1024 / 1024 < 10;
      if (!isExcel) {
         proxy.$modal.msgError("上传文件只能是 xlsx/xls 格式!");
         return false;
      }
      if (!isLt10M) {
         proxy.$modal.msgError("上传文件大小不能超过 10MB!");
         return false;
      }
      return true;
   },
   onChange: (file, fileList) => {
      console.log('文件状态改变', file, fileList);
   },
   onProgress: (event, file, fileList) => {
      console.log('上传中...', event.percent);
   },
   onSuccess: (response, file, fileList) => {
      console.log('上传成功', response, file, fileList);
      importUpload.isUploading = false;
      if (response.code === 200) {
         proxy.$modal.msgSuccess("导入成功");
         importUpload.open = false;
         if (importUploadRef.value) {
            importUploadRef.value.clearFiles();
         }
         getList();
      } else {
         proxy.$modal.msgError(response.msg || "导入失败");
      }
   },
   onError: (error, file, fileList) => {
      console.error('上传失败', error, file, fileList);
      importUpload.isUploading = false;
      proxy.$modal.msgError("导入失败,请重试");
   },
});
const changeDaterange = (value) => {
   if (value) {
      searchForm.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
      searchForm.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
   } else {
      searchForm.entryDateStart = undefined;
      searchForm.entryDateEnd = undefined;
   }
   handleQuery();
};
// 查询列表
/** 搜索按钮操作 */
const handleQuery = () => {
   // 只有在点击搜索按钮时才重置页码到第一页
   // 避免表单字段change事件干扰分页
   if (arguments.length === 0) {
      page.current = 1;
   }
   expandedRowKeys.value = [];
   getList();
};
const paginationChange = (obj) => {
   page.current = obj.page;
   page.size = obj.limit;
   getList();
};
const getList = () => {
   tableLoading.value = true;
   const { entryDate, ...rest } = searchForm;
   // 将范围日期字段传递给后端
   const params = { ...rest, ...page };
   // 移除录入日期的默认值设置,只保留范围日期字段
   delete params.entryDate;
   return ledgerListPage(params)
      .then((res) => {
         tableLoading.value = false;
         tableData.value = res.records;
         tableData.value.map((item) => {
            item.children = [];
         });
         total.value = res.total;
         return res;
      })
      .catch(() => {
         tableLoading.value = false;
      });
};
// 获取产品大类tree数据
const getProductOptions = () => {
   // 返回 Promise,便于在编辑产品时等待加载完成
   return productTreeList().then((res) => {
      productOptions.value = convertIdToValue(res);
      return productOptions.value;
   });
};
const formattedNumber = (row, column, cellValue) => {
   return parseFloat(cellValue).toFixed(2);
};
// 获取tree子数据
const getModels = (value) => {
   productForm.value.productCategory = findNodeById(productOptions.value, value);
   modelList({ id: value }).then((res) => {
      modelOptions.value = res;
   });
};
const getProductModel = (value) => {
   const index = modelOptions.value.findIndex((item) => item.id === value);
   if (index !== -1) {
      productForm.value.specificationModel = modelOptions.value[index].model;
      productForm.value.unit = modelOptions.value[index].unit;
   } else {
      productForm.value.specificationModel = null;
      productForm.value.unit = null;
   }
};
const findNodeById = (nodes, productId) => {
   for (let i = 0; i < nodes.length; i++) {
      if (nodes[i].value === productId) {
         return nodes[i].label; // 找到节点,返回该节点
      }
      if (nodes[i].children && nodes[i].children.length > 0) {
         const foundNode = findNodeById(nodes[i].children, productId);
         if (foundNode) {
            return foundNode; // 在子节点中找到,返回该节点
         }
      }
   }
   return null; // 没有找到节点,返回null
};
function convertIdToValue(data) {
   return data.map((item) => {
      const { id, children, ...rest } = item;
      const newItem = {
         ...rest,
         value: id, // 将 id 改为 value
      };
      if (children && children.length > 0) {
         newItem.children = convertIdToValue(children);
      }
      return newItem;
   });
}
// 根据名称反查产品大类 id,便于仅存名称时的反显
function findNodeIdByLabel(nodes, label) {
   if (!label) return null;
   for (let i = 0; i < nodes.length; i++) {
      const node = nodes[i];
      if (node.label === label) return node.value;
      if (node.children && node.children.length > 0) {
         const found = findNodeIdByLabel(node.children, label);
         if (found !== null && found !== undefined) return found;
      }
   }
   return null;
}
// 表格选择数据
const handleSelectionChange = (selection) => {
   // 过滤掉子数据
   selectedRows.value = selection.filter((item) => item.children !== undefined);
   console.log("selection", selectedRows.value);
};
const productSelected = (selectedRows) => {
   productSelectedRows.value = selectedRows;
};
const expandedRowKeys = ref([]);
// 展开行
const expandChange = (row, expandedRows) => {
   if (expandedRows.length > 0) {
      expandedRowKeys.value = [];
      try {
         productList({ salesLedgerId: row.id, type: 1 }).then((res) => {
            const index = tableData.value.findIndex((item) => item.id === row.id);
            if (index > -1) {
               tableData.value[index].children = res.data;
            }
            expandedRowKeys.value.push(row.id);
         });
      } catch (error) {
         console.log(error);
      }
   } else {
      expandedRowKeys.value = [];
   }
};
// 添加表行类名方法
const tableRowClassName = ({ row }) => {
  if (!row.deliveryDate) return '';
  if (row.isFh) return '';
  const diff = row.deliveryDaysDiff;
  if (diff === 15) {
    return 'yellow';
  } else if (diff === 10) {
    return 'pink';
  } else if (diff === 2) {
    return 'purple';
  } else if (diff < 2) {
    return 'red';
  }
};
// 主表合计方法
const summarizeMainTable = (param) => {
   return proxy.summarizeTable(param, [
      "contractAmount",
      "taxInclusiveTotalPrice",
      "taxExclusiveTotalPrice",
   ]);
};
// 子表合计方法
const summarizeChildrenTable = (param) => {
   return proxy.summarizeTable(param, [
      "taxInclusiveUnitPrice",
      "taxInclusiveTotalPrice",
      "taxExclusiveTotalPrice",
   ]);
};
// 打开弹框
const openForm = async (type, row) => {
   operationType.value = type;
   form.value = {};
   productData.value = [];
   selectedQuotation.value = null;
   let userLists = await userListNoPage();
   userList.value = userLists.data;
   customerList().then((res) => {
      customerOption.value = res;
   });
   form.value.entryPerson = userStore.id;
   if (type === "add") {
      // 新增时设置录入日期为当天
      form.value.entryDate = getCurrentDate();
      // 签订日期默认为当天
      form.value.executionDate = getCurrentDate();
   } else {
      currentId.value = row.id;
      getSalesLedgerWithProducts({ id: row.id, type: 1 }).then((res) => {
         form.value = { ...res };
         form.value.entryPerson = Number(res.entryPerson);
         productData.value = form.value.productData;
         fileList.value = form.value.salesLedgerFiles;
      });
   }
   // let userAll = await userStore.getInfo()
   // userList.value.forEach(element => {
   //   if(userAll.user.nickName === element.nickName && userAll.user.userName === element.userName) {
   //     form.value.entryPerson = userAll.user.userId // 设置默认业务员为当前用户
   //   }
   // });
   form.value.entryDate = getCurrentDate(); // 设置默认录入日期为当前日期
   dialogFormVisible.value = true;
};
// 打开报价单选择弹窗(仅审批通过)
const openQuotationDialog = async () => {
   if (operationType.value === "view") return;
   quotationDialogVisible.value = true;
   // 打开弹窗时重置分页到第一页
   quotationPage.current = 1;
   // 先确保客户列表已加载,便于后续回填 customerId
   if (!customerOption.value || customerOption.value.length === 0) {
      try {
         const res = await customerList();
         customerOption.value = res;
      } catch (e) {
         // ignore,允许用户后续手动选择客户
      }
   }
   await fetchQuotationList();
};
const fetchQuotationList = async () => {
   quotationLoading.value = true;
   try {
      const params = {
         // 后端分页字段:current / size
         current: quotationPage.current,
         size: quotationPage.size,
         ...quotationSearchForm,
         status: "通过",
      };
      const res = await getQuotationList(params);
      quotationList.value = res?.data?.records || [];
      quotationPage.total = res?.data?.total || 0;
   } finally {
      quotationLoading.value = false;
   }
};
const resetQuotationSearch = async () => {
   quotationSearchForm.quotationNo = "";
   quotationSearchForm.customer = "";
   quotationPage.current = 1;
   await fetchQuotationList();
};
// 报价单弹框分页切换
const quotationPaginationChange = (obj) => {
   quotationPage.current = obj.page;
   quotationPage.size = obj.limit;
   fetchQuotationList();
};
// 选中报价单后回填到台账表单
const applyQuotation = (row) => {
   if (!row) return;
   selectedQuotation.value = row;
   // 业务员
   form.value.salesman = (row.salesperson || "").trim();
   // 客户名称 -> customerId
   const qCustomerName = String(row.customer || "").trim();
   const customer = (customerOption.value || []).find((c) => {
      const name = String(c.customerName || "").trim();
      return name === qCustomerName || name.includes(qCustomerName) || qCustomerName.includes(name);
   });
   if (customer?.id) {
      form.value.customerId = customer.id;
   } else {
      // 如果找不到,保留原值(允许用户手动选择/不打断已有输入)
      form.value.customerId = form.value.customerId || "";
   }
   // 产品信息映射:报价 products -> 台账 productData
   const products = Array.isArray(row.products) ? row.products : [];
   productData.value = products.map((p) => {
      const quantity = Number(p.quantity ?? 0) || 0;
      const unitPrice = Number(p.unitPrice ?? 0) || 0;
      const taxRate = "13"; // 默认 13%,便于直接提交(如需可在产品中自行修改)
      const taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
      const taxExclusiveTotalPrice = proxy.calculateTaxExclusiveTotalPrice(taxInclusiveTotalPrice, taxRate);
      return {
         // 台账字段
         productCategory: p.product || p.productName || "",
         specificationModel: p.specification || "",
         unit: p.unit || "",
         quantity: quantity,
         taxRate: taxRate,
         taxInclusiveUnitPrice: unitPrice.toFixed(2),
         taxInclusiveTotalPrice: taxInclusiveTotalPrice,
         taxExclusiveTotalPrice: taxExclusiveTotalPrice,
         invoiceType: "增普票",
      };
   });
   quotationDialogVisible.value = false;
};
function changs(val) {
   console.log(val);
}
// 上传前校检
function handleBeforeUpload(file) {
   // 校检文件大小
   // if (file.size > 1024 * 1024 * 10) {
   //   proxy.$modal.msgError("上传文件大小不能超过10MB!");
   //   return false;
   // }
   proxy.$modal.loading("正在上传文件,请稍候...");
   return true;
}
// 上传失败
function handleUploadError(err) {
   proxy.$modal.msgError("上传文件失败");
   proxy.$modal.closeLoading();
}
// 上传成功回调
function handleUploadSuccess(res, file, uploadFiles) {
   proxy.$modal.closeLoading();
   if (res.code === 200) {
      file.tempId = res.data.tempId;
      proxy.$modal.msgSuccess("上传成功");
   } else {
      proxy.$modal.msgError(res.msg);
      proxy.$refs.fileUpload.handleRemove(file);
   }
}
// 移除文件
function handleRemove(file) {
   if (operationType.value === "edit") {
      let ids = [];
      ids.push(file.id);
      delLedgerFile(ids).then((res) => {
         proxy.$modal.msgSuccess("删除成功");
      });
   }
}
// 提交表单
const submitForm = () => {
   proxy.$refs["formRef"].validate((valid) => {
      if (valid) {
         console.log('productData.value--', productData.value)
         if (productData.value !== null && productData.value.length > 0) {
            form.value.productData = proxy.HaveJson(productData.value);
         } else {
            proxy.$modal.msgWarning("请添加产品信息");
            return;
         }
         let tempFileIds = [];
         if (fileList.value !== null && fileList.value.length > 0) {
            tempFileIds = fileList.value.map((item) => item.tempId);
         }
         form.value.tempFileIds = tempFileIds;
         form.value.type = 1;
         addOrUpdateSalesLedger(form.value).then((res) => {
            proxy.$modal.msgSuccess("提交成功");
            closeDia();
            getList();
         });
      }
   });
};
// 关闭弹框
const closeDia = () => {
   proxy.resetForm("formRef");
   dialogFormVisible.value = false;
};
const productIndex = ref(0);
// 打开产品弹框
const openProductForm = async (type, row, index) => {
   // 编辑时检查产品是否已发货或审核通过
   if (type === "edit" && isProductShipped(row)) {
      proxy.$modal.msgWarning("已发货或审核通过的产品不能编辑");
      return;
   }
   productOperationType.value = type;
   productForm.value = {};
   proxy.resetForm("productFormRef");
   if (type === "edit") {
      productForm.value = { ...row };
      productIndex.value = index;
      // 编辑时根据产品大类名称反查 tree 节点 id,并加载规格型号列表
      try {
         const options = productOptions.value && productOptions.value.length > 0
            ? productOptions.value
            : await getProductOptions();
         const categoryId = findNodeIdByLabel(options, productForm.value.productCategory);
         if (categoryId) {
            const models = await modelList({ id: categoryId });
            modelOptions.value = models || [];
            // 根据当前规格型号名称反查并设置 productModelId,便于下拉框显示已选值
            const currentModel = (modelOptions.value || []).find(
               (m) => m.model === productForm.value.specificationModel
            );
            if (currentModel) {
               productForm.value.productModelId = currentModel.id;
            }
         }
      } catch (e) {
         // 加载失败时保持可编辑,不中断弹窗
         console.error("加载产品规格型号失败", e);
      }
   } else {
      getProductOptions()
   }
   productFormVisible.value = true;
};
// 提交产品表单
const submitProduct = () => {
   proxy.$refs["productFormRef"].validate((valid) => {
      if (valid) {
         if (operationType.value === "edit") {
            submitProductEdit();
         } else {
            if(productOperationType.value === "add"){
               productData.value.push({ ...productForm.value });
            }else{
               productData.value[productIndex.value] = { ...productForm.value }
            }
            closeProductDia();
         }
      }
   });
};
const submitProductEdit = () => {
   productForm.value.salesLedgerId = currentId.value;
   productForm.value.type = 1
   addOrUpdateSalesLedgerProduct(productForm.value).then((res) => {
      proxy.$modal.msgSuccess("提交成功");
      closeProductDia();
      getSalesLedgerWithProducts({ id: currentId.value, type: 1 }).then((res) => {
         productData.value = res.productData;
      });
   });
};
// 删除产品
const deleteProduct = () => {
   if (productSelectedRows.value.length === 0) {
      proxy.$modal.msgWarning("请选择数据");
      return;
   }
   // 检查是否有已发货或审核通过的产品
   const shippedProducts = productSelectedRows.value.filter(row => isProductShipped(row));
   if (shippedProducts.length > 0) {
      proxy.$modal.msgWarning("已发货或审核通过的产品不能删除");
      return;
   }
   if (operationType.value === "add") {
      productSelectedRows.value.forEach((selectedRow) => {
         const index = productData.value.findIndex(
            (product) => product.id === selectedRow.id
         );
         if (index !== -1) {
            productData.value.splice(index, 1);
         }
      });
   } else {
      let ids = [];
      if (productSelectedRows.value.length > 0) {
         ids = productSelectedRows.value.map((item) => item.id);
      }
      ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "导出", {
         confirmButtonText: "确认",
         cancelButtonText: "取消",
         type: "warning",
      })
         .then(() => {
            delProduct(ids).then((res) => {
               proxy.$modal.msgSuccess("删除成功");
               closeProductDia();
               getSalesLedgerWithProducts({ id: currentId.value, type: 1 }).then(
                  (res) => {
                     productData.value = res.productData;
                  }
               );
            });
         })
         .catch(() => {
            proxy.$modal.msg("已取消");
         });
   }
};
// 关闭产品弹框
const closeProductDia = () => {
   proxy.resetForm("productFormRef");
   productFormVisible.value = false;
};
// 导入
const handleImport = () => {
   importUpload.title = "导入销售台账";
   importUpload.open = true;
   if (importUploadRef.value) {
      importUploadRef.value.clearFiles();
   }
};
// 下载导入模板
const downloadTemplate = () => {
   proxy.download("/sales/ledger/exportTemplate", {}, "销售台账导入模板.xlsx");
};
// 提交导入文件
const submitImportFile = () => {
   importUpload.isUploading = true;
   proxy.$refs["importUploadRef"].submit();
};
// 导出
const handleOut = () => {
   ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
      confirmButtonText: "确认",
      cancelButtonText: "取消",
      type: "warning",
   })
      .then(() => {
         proxy.download("/sales/ledger/export", {}, "销售台账.xlsx");
      })
      .catch(() => {
         proxy.$modal.msg("已取消");
      });
};
/** 判断单个产品是否已发货(根据shippingStatus判断,已发货或审核通过不可编辑和删除) */
const isProductShipped = (product) => {
   if (!product) return false;
   const status = String(product.shippingStatus || "").trim();
   // 如果发货状态是"已发货"或"审核通过",则不可编辑和删除
   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 === "已发货";
   });
};
// 删除
const handleDelete = async () => {
   if (selectedRows.value.length === 0) {
      proxy.$modal.msgWarning("请选择数据");
      return;
   }
   const ids = selectedRows.value.map((item) => item.id);
   // 检查是否有已进行发货或发货完成的销售订单,若有则不允许删除
   const cannotDeleteNames = [];
   for (const row of selectedRows.value) {
      let products = row.children && row.children.length > 0 ? row.children : null;
      if (!products) {
         try {
            const res = await productList({ salesLedgerId: row.id, type: 1 });
            products = res.data || [];
         } catch {
            products = [];
         }
      }
      if (hasShippedProducts(products)) {
         cannotDeleteNames.push(row.salesContractNo || `ID:${row.id}`);
      }
   }
   if (cannotDeleteNames.length > 0) {
      proxy.$modal.msgWarning("已进行发货或发货完成的销售订单不能删除:" + cannotDeleteNames.join("、"));
      return;
   }
   ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "导出", {
      confirmButtonText: "确认",
      cancelButtonText: "取消",
      type: "warning",
   })
      .then(() => {
         delLedger(ids).then((res) => {
            proxy.$modal.msgSuccess("删除成功");
            getList();
         });
      })
      .catch(() => {
         proxy.$modal.msg("已取消");
      });
};
// 打印功能
const handlePrint = async () => {
   if (selectedRows.value.length === 0) {
      proxy.$modal.msgWarning("请选择要打印的数据");
      return;
   }
   // 显示加载状态
   proxy.$modal.loading("正在获取产品数据,请稍候...");
   try {
      // 为每个选中的销售台账记录查询对应的产品数据
      const printDataWithProducts = [];
      for (const row of selectedRows.value) {
         try {
            // 调用productList接口查询产品数据
            const productRes = await productList({ salesLedgerId: row.id, type: 1 });
            // 将产品数据整合到销售台账记录中
            const rowWithProducts = {
               ...row,
               products: productRes.data || []
            };
            printDataWithProducts.push(rowWithProducts);
         } catch (error) {
            console.error(`获取销售台账 ${row.id} 的产品数据失败:`, error);
            // 即使某个记录的产品数据获取失败,也要包含该记录
            printDataWithProducts.push({
               ...row,
               products: []
            });
         }
      }
      printData.value = printDataWithProducts;
      console.log('打印数据(包含产品):', printData.value);
      printPreviewVisible.value = true;
   } catch (error) {
      console.error('获取产品数据失败:', error);
      proxy.$modal.msgError("获取产品数据失败,请重试");
   } finally {
      proxy.$modal.closeLoading();
   }
};
// 执行打印
const executePrint = () => {
   console.log('开始执行打印,数据条数:', printData.value.length);
   console.log('打印数据:', printData.value);
   // 创建一个新的打印窗口
   const printWindow = window.open('', '_blank', 'width=800,height=600');
   // 构建打印内容
   let printContent = `
    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="UTF-8">
      <title>打印预览</title>
      <style>
        body {
          margin: 0;
          padding: 0;
          font-family: "SimSun", serif;
          background: white;
        }
                                                     .print-page {
            width: 200mm;
            height: 75mm;
            padding: 10mm;
            padding-left: 20mm;
            background: white;
            box-sizing: border-box;
            page-break-after: always;
            page-break-inside: avoid;
          }
         .print-page:last-child {
           page-break-after: avoid;
         }
        .delivery-note {
          width: 100%;
          height: 100%;
          font-size: 12px;
          line-height: 1.2;
          display: flex;
          flex-direction: column;
          color: #000;
        }
        .header {
          text-align: center;
          margin-bottom: 8px;
        }
        .company-name {
          font-size: 18px;
          font-weight: bold;
          margin-bottom: 4px;
        }
        .document-title {
          font-size: 16px;
          font-weight: bold;
        }
        .info-section {
          margin-bottom: 8px;
          display: flex;
          justify-content: space-between;
          align-items: center;
        }
        .info-row {
          line-height: 20px;
        }
        .label {
          font-weight: bold;
          width: 60px;
          font-size: 12px;
        }
        .value {
          margin-right: 20px;
          min-width: 80px;
          font-size: 12px;
        }
                 .table-section {
                 margin-bottom: 40px;
          //  flex: 0.6;
         }
        .product-table {
          width: 100%;
          border-collapse: collapse;
          border: 1px solid #000;
        }
                 .product-table th, .product-table td {
           border: 1px solid #000;
           padding: 6px;
           text-align: center;
           font-size: 12px;
           line-height: 1.4;
         }
        .product-table th {
          font-weight: bold;
        }
        .total-value {
          font-weight: bold;
        }
        .footer-section {
          margin-top: auto;
        }
        .footer-row {
          display: flex;
          margin-bottom: 3px;
          line-height: 22px;
          justify-content: space-between;
        }
        .footer-item {
          display: flex;
          margin-right: 20px;
        }
        .footer-item .label {
          font-weight: bold;
          width: 80px;
          font-size: 12px;
        }
        .footer-item .value {
          min-width: 80px;
          font-size: 12px;
        }
        .address-item .address-value {
          min-width: 200px;
        }
        @media print {
          body {
            margin: 0;
            padding: 0;
          }
                     .print-page {
             margin: 0;
             padding: 10mm;
             /* padding-left: 20mm; */
             page-break-inside: avoid;
             page-break-after: always;
           }
           .print-page:last-child {
             page-break-after: avoid;
           }
        }
      </style>
    </head>
    <body>
  `;
   // 为每条数据生成打印页面
   printData.value.forEach((item, index) => {
      printContent += `
      <div class="print-page">
        <div class="delivery-note">
          <div class="header">
            <div class="document-title">零售发货单</div>
          </div>
          <div class="info-section">
            <div class="info-row">
              <div>
                <span class="label">发货日期:</span>
                <span class="value">${formatDate(item.createTime)}</span>
              </div>
              <div>
                <span class="label">客户名称:</span>
                <span class="value">${item.customerName}</span>
              </div>
            </div>
            <div class="info-row">
              <span class="label">单号:</span>
              <span class="value">${item.salesContractNo || ''}</span>
            </div>
          </div>
          <div class="table-section">
            <table class="product-table">
              <thead>
                <tr>
                  <th>产品名称</th>
                  <th>规格型号</th>
                  <th>单位</th>
                  <th>单价</th>
                  <th>零售数量</th>
                  <th>零售金额</th>
                </tr>
              </thead>
              <tbody>
                ${item.products && item.products.length > 0 ?
         item.products.map(product => `
                    <tr>
                      <td>${product.productCategory || ''}</td>
                      <td>${product.specificationModel || ''}</td>
                      <td>${product.unit || ''}</td>
                      <td>${product.taxInclusiveUnitPrice || '0'}</td>
                      <td>${product.quantity || '0'}</td>
                      <td>${product.taxInclusiveTotalPrice || '0'}</td>
                    </tr>
                  `).join('') :
         '<tr><td colspan="6" style="text-align: center; color: #999;">暂无产品数据</td></tr>'
      }
              </tbody>
              <tfoot>
                <tr>
                  <td class="label">合计</td>
                  <td class="total-value"></td>
                  <td class="total-value"></td>
                  <td class="total-value"></td>
                  <td class="total-value">${getTotalQuantityForPrint(item.products)}</td>
                  <td class="total-value">${getTotalAmountForPrint(item.products)}</td>
                </tr>
              </tfoot>
            </table>
          </div>
          <div class="footer-section">
            <div class="footer-row">
              <div class="footer-item">
                <span class="label">收货电话:</span>
                <span class="value"></span>
              </div>
              <div class="footer-item">
                <span class="label">收货人:</span>
                <span class="value"></span>
              </div>
              <div class="footer-item address-item">
                <span class="label">收货地址:</span>
                <span class="value address-value"></span>
              </div>
            </div>
            <div class="footer-row">
              <div class="footer-item">
                <span class="label">操作员:</span>
                <span class="value">${userStore.nickName || '撕开前'}</span>
              </div>
              <div class="footer-item">
                <span class="label">打印日期:</span>
                <span class="value">${formatDateTime(new Date())}</span>
              </div>
            </div>
          </div>
        </div>
      </div>
    `;
   });
   printContent += `
    </body>
    </html>
  `;
   // 写入内容到新窗口
   printWindow.document.write(printContent);
   printWindow.document.close();
   // 等待内容加载完成后打印
   printWindow.onload = () => {
      setTimeout(() => {
         printWindow.print();
         printWindow.close();
         printPreviewVisible.value = false;
      }, 500);
   };
};
// 格式化日期
const formatDate = (dateString) => {
   if (!dateString) return getCurrentDate();
   const date = new Date(dateString);
   const year = date.getFullYear();
   const month = String(date.getMonth() + 1).padStart(2, "0");
   const day = String(date.getDate()).padStart(2, "0");
   return `${year}/${month}/${day}`;
};
// 格式化日期时间
const formatDateTime = (date) => {
   const year = date.getFullYear();
   const month = String(date.getMonth() + 1).padStart(2, "0");
   const day = String(date.getDate()).padStart(2, "0");
   const hours = String(date.getHours()).padStart(2, "0");
   const minutes = String(date.getMinutes()).padStart(2, "0");
   const seconds = String(date.getSeconds()).padStart(2, "0");
   return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`;
};
// 计算产品总数量
const getTotalQuantity = (products) => {
   if (!products || products.length === 0) return '0';
   const total = products.reduce((sum, product) => {
      return sum + (parseFloat(product.quantity) || 0);
   }, 0);
   return total.toFixed(2);
};
// 计算产品总金额
const getTotalAmount = (products) => {
   if (!products || products.length === 0) return '0';
   const total = products.reduce((sum, product) => {
      return sum + (parseFloat(product.taxInclusiveTotalPrice) || 0);
   }, 0);
   return total.toFixed(2);
};
// 用于打印的计算函数
const getTotalQuantityForPrint = (products) => {
   if (!products || products.length === 0) return '0';
   const total = products.reduce((sum, product) => {
      return sum + (parseFloat(product.quantity) || 0);
   }, 0);
   return total.toFixed(2);
};
const getTotalAmountForPrint = (products) => {
   if (!products || products.length === 0) return '0';
   const total = products.reduce((sum, product) => {
      return sum + (parseFloat(product.taxInclusiveTotalPrice) || 0);
   }, 0);
   return total.toFixed(2);
};
const mathNum = () => {
   console.log("productForm.value", productForm.value);
   if (!productForm.value.taxInclusiveUnitPrice) {
      return;
   }
   if (!productForm.value.quantity) {
      return;
   }
   // 含税总价计算
   productForm.value.taxInclusiveTotalPrice =
      proxy.calculateTaxIncludeTotalPrice(
         productForm.value.taxInclusiveUnitPrice,
         productForm.value.quantity
      );
   if (productForm.value.taxRate) {
      // 不含税总价计算
      productForm.value.taxExclusiveTotalPrice =
         proxy.calculateTaxExclusiveTotalPrice(
            productForm.value.taxInclusiveTotalPrice,
            productForm.value.taxRate
         );
   }
};
// 根据含税总价计算含税单价和数量
const calculateFromTotalPrice = () => {
   if (isCalculating.value) return;
   const totalPrice = parseFloat(productForm.value.taxInclusiveTotalPrice);
   const quantity = parseFloat(productForm.value.quantity);
   if (!totalPrice || !quantity || quantity <= 0) {
      return;
   }
   isCalculating.value = true;
   // 计算含税单价 = 含税总价 / 数量
   productForm.value.taxInclusiveUnitPrice = (totalPrice / quantity).toFixed(2);
   // 如果有税率,计算不含税总价
   if (productForm.value.taxRate) {
      productForm.value.taxExclusiveTotalPrice =
         proxy.calculateTaxExclusiveTotalPrice(
            totalPrice,
            productForm.value.taxRate
         );
   }
   isCalculating.value = false;
};
// 根据不含税总价计算含税单价和数量
const calculateFromExclusiveTotalPrice = () => {
   if (!productForm.value.taxRate) {
      proxy.$modal.msgWarning("请先选择税率");
      return;
   }
   if (isCalculating.value) return;
   const exclusiveTotalPrice = parseFloat(productForm.value.taxExclusiveTotalPrice);
   const quantity = parseFloat(productForm.value.quantity);
   const taxRate = parseFloat(productForm.value.taxRate);
   if (!exclusiveTotalPrice || !quantity || quantity <= 0 || !taxRate) {
      return;
   }
   isCalculating.value = true;
   // 先计算含税总价 = 不含税总价 / (1 - 税率/100)
   const taxRateDecimal = taxRate / 100;
   const inclusiveTotalPrice = exclusiveTotalPrice / (1 - taxRateDecimal);
   productForm.value.taxInclusiveTotalPrice = inclusiveTotalPrice.toFixed(2);
   // 计算含税单价 = 含税总价 / 数量
   productForm.value.taxInclusiveUnitPrice = (inclusiveTotalPrice / quantity).toFixed(2);
   isCalculating.value = false;
};
// 根据数量变化计算总价
const calculateFromQuantity = () => {
   if (!productForm.value.taxRate) {
      proxy.$modal.msgWarning("请先选择税率");
      return;
   }
   if (isCalculating.value) return;
   const quantity = parseFloat(productForm.value.quantity);
   const unitPrice = parseFloat(productForm.value.taxInclusiveUnitPrice);
   if (!quantity || quantity <= 0 || !unitPrice) {
      return;
   }
   isCalculating.value = true;
   // 计算含税总价
   productForm.value.taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
   // 如果有税率,计算不含税总价
   if (productForm.value.taxRate) {
      productForm.value.taxExclusiveTotalPrice =
         proxy.calculateTaxExclusiveTotalPrice(
            productForm.value.taxInclusiveTotalPrice,
            productForm.value.taxRate
         );
   }
   isCalculating.value = false;
};
// 根据含税单价变化计算总价
const calculateFromUnitPrice = () => {
   if (!productForm.value.taxRate) {
      proxy.$modal.msgWarning("请先选择税率");
      return;
   }
   if (isCalculating.value) return;
   const quantity = parseFloat(productForm.value.quantity);
   const unitPrice = parseFloat(productForm.value.taxInclusiveUnitPrice);
   if (!quantity || quantity <= 0 || !unitPrice) {
      return;
   }
   isCalculating.value = true;
   // 计算含税总价
   productForm.value.taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
   // 如果有税率,计算不含税总价
   if (productForm.value.taxRate) {
      productForm.value.taxExclusiveTotalPrice =
         proxy.calculateTaxExclusiveTotalPrice(
            productForm.value.taxInclusiveTotalPrice,
            productForm.value.taxRate
         );
   }
   isCalculating.value = false;
};
// 根据税率变化计算不含税总价
const calculateFromTaxRate = () => {
   if (!productForm.value.taxRate) {
      proxy.$modal.msgWarning("请先选择税率");
      return;
   }
   if (isCalculating.value) return;
   const inclusiveTotalPrice = parseFloat(productForm.value.taxInclusiveTotalPrice);
   const taxRate = parseFloat(productForm.value.taxRate);
   if (!inclusiveTotalPrice || !taxRate) {
      return;
   }
   isCalculating.value = true;
   // 计算不含税总价
   productForm.value.taxExclusiveTotalPrice =
      proxy.calculateTaxExclusiveTotalPrice(
         inclusiveTotalPrice,
         taxRate
      );
   isCalculating.value = false;
};
/**
 * 获取发货状态文本
 * @param row 行数据
 */
const getShippingStatusText = (row) => {
   // 如果已发货(有发货日期或车牌号),显示"已发货"
   if (row.shippingDate || row.shippingCarNumber) {
      return '已发货';
   }
   // 获取发货状态字段
   const status = row.shippingStatus;
   // 如果状态为空或未定义,默认为"待发货"
   if (status === null || status === undefined || status === '') {
      return '待发货';
   }
   // 状态是字符串
   const statusStr = String(status).trim();
   const statusTextMap = {
      '待发货': '待发货',
      '待审核': '待审核',
      '审核中': '审核中',
      '审核拒绝': '审核拒绝',
      '审核通过': '审核通过',
      '已发货': '已发货'
   };
   return statusTextMap[statusStr] || '待发货';
};
/**
 * 获取发货状态标签类型(颜色)
 * @param row 行数据
 */
const getShippingStatusType = (row) => {
   // 如果已发货(有发货日期或车牌号),显示绿色
   if (row.shippingDate || row.shippingCarNumber) {
      return 'success';
   }
   // 获取发货状态字段
   const status = row.shippingStatus;
   // 如果状态为空或未定义,默认为灰色(待发货)
   if (status === null || status === undefined || status === '') {
      return 'info';
   }
   // 状态是字符串
   const statusStr = String(status).trim();
   const typeTextMap = {
      '待发货': 'info',
      '待审核': 'info',
      '审核中': 'warning',
      '审核拒绝': 'danger',
      '审核通过': 'success',
      '已发货': 'success'
   };
   return typeTextMap[statusStr] || 'info';
};
/**
 * 判断是否可以发货
 * 只有在产品状态是充足,发货状态是待发货和审核拒绝的时候才可以发货
 * @param row 行数据
 */
const canShip = (row) => {
   // 产品状态必须是充足(approveStatus === 1)
   if (row.approveStatus !== 1) {
      return false;
   }
   // 获取发货状态
   const shippingStatus = row.shippingStatus;
   // 如果已发货(有发货日期或车牌号),不能再次发货
   if (row.shippingDate || row.shippingCarNumber) {
      return false;
   }
   // 发货状态必须是"待发货"或"审核拒绝"
   const statusStr = shippingStatus ? String(shippingStatus).trim() : '';
   return statusStr === '待发货' || statusStr === '审核拒绝';
};
/**
 * 下载文件
 *
 * @param row 下载文件的相关信息对象
 */
const fileListRef = ref(null)
const fileListDialogVisible = ref(false)
const downLoadFile = (row) => {
   getSalesLedgerWithProducts({ id: row.id, type: 1 }).then((res) => {
      if (fileListRef.value) {
         fileListRef.value.open(res.salesLedgerFiles)
      }
   });
}
// 打开发货弹框
const openDeliveryForm = (row) => {
   // 检查是否可以发货
   if (!canShip(row)) {
      proxy.$modal.msgWarning("只有在产品状态是充足,发货状态是待发货或审核拒绝的时候才可以发货");
      return;
   }
   currentDeliveryRow.value = row;
  deliveryForm.value = {
    type: "货车",
  // 发货审批人节点(仿协同审批 infoFormDia.vue)
  const approverNodes = ref([{ id: 1, userId: null }]);
  let nextApproverId = 2;
  const addApproverNode = () => {
    approverNodes.value.push({ id: nextApproverId++, userId: null });
  };
  // 重置审批人节点(默认一个空节点)
  approverNodes.value = [{ id: 1, userId: null }];
  nextApproverId = 2;
   deliveryFormVisible.value = true;
};
  const removeApproverNode = index => {
    approverNodes.value.splice(index, 1);
  };
// 提交发货表单
const submitDelivery = () => {
  proxy.$refs["deliveryFormRef"].validate((valid) => {
    if (valid) {
      // 审批人必填校验(所有节点都要选人)
      const hasEmptyApprover = approverNodes.value.some(node => !node.userId);
      if (hasEmptyApprover) {
        proxy.$modal.msgError("请为所有审批节点选择审批人!");
        return;
  // 导入相关
  const importUploadRef = ref(null);
  const importUpload = reactive({
    title: "导入销售台账",
    open: false,
    url: import.meta.env.VITE_APP_BASE_API + "/sales/ledger/import",
    headers: { Authorization: "Bearer " + getToken() },
    isUploading: false,
    beforeUpload: file => {
      const isExcel = file.name.endsWith(".xlsx") || file.name.endsWith(".xls");
      const isLt10M = file.size / 1024 / 1024 < 10;
      if (!isExcel) {
        proxy.$modal.msgError("上传文件只能是 xlsx/xls 格式!");
        return false;
      }
      const approveUserIds = approverNodes.value.map(node => node.userId).join(",");
      // 保存当前展开的行ID,以便发货后重新加载子表格数据
      const currentExpandedKeys = [...expandedRowKeys.value];
      const salesLedgerId = currentDeliveryRow.value.salesLedgerId;
      addShippingInfo({
        salesLedgerId: salesLedgerId,
        salesLedgerProductId: currentDeliveryRow.value.id,
        type: deliveryForm.value.type,
            approveUserIds,
      if (!isLt10M) {
        proxy.$modal.msgError("上传文件大小不能超过 10MB!");
        return false;
      }
      return true;
    },
    onChange: (file, fileList) => {
      console.log("文件状态改变", file, fileList);
    },
    onProgress: (event, file, fileList) => {
      console.log("上传中...", event.percent);
    },
    onSuccess: (response, file, fileList) => {
      console.log("上传成功", response, file, fileList);
      importUpload.isUploading = false;
      if (response.code === 200) {
        proxy.$modal.msgSuccess("导入成功");
        importUpload.open = false;
        if (importUploadRef.value) {
          importUploadRef.value.clearFiles();
        }
        getList();
      } else {
        proxy.$modal.msgError(response.msg || "导入失败");
      }
    },
    onError: (error, file, fileList) => {
      console.error("上传失败", error, file, fileList);
      importUpload.isUploading = false;
      proxy.$modal.msgError("导入失败,请重试");
    },
  });
  const changeDaterange = value => {
    if (value) {
      searchForm.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
      searchForm.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
    } else {
      searchForm.entryDateStart = undefined;
      searchForm.entryDateEnd = undefined;
    }
    handleQuery();
  };
  // 查询列表
  /** 搜索按钮操作 */
  const handleQuery = () => {
    // 只有在点击搜索按钮时才重置页码到第一页
    // 避免表单字段change事件干扰分页
    if (arguments.length === 0) {
      page.current = 1;
    }
    expandedRowKeys.value = [];
    getList();
  };
  const paginationChange = obj => {
    page.current = obj.page;
    page.size = obj.limit;
    getList();
  };
  const getList = () => {
    tableLoading.value = true;
    const { entryDate, ...rest } = searchForm;
    // 将范围日期字段传递给后端
    const params = { ...rest, ...page };
    // 移除录入日期的默认值设置,只保留范围日期字段
    delete params.entryDate;
    return ledgerListPage(params)
      .then(res => {
        tableLoading.value = false;
        tableData.value = res.records;
        tableData.value.map(item => {
          item.children = [];
        });
        total.value = res.total;
        return res;
      })
        .then(() => {
      .catch(() => {
        tableLoading.value = false;
      });
  };
  // 获取产品大类tree数据
  const getProductOptions = () => {
    // 返回 Promise,便于在编辑产品时等待加载完成
    return productTreeList().then(res => {
      productOptions.value = convertIdToValue(res);
      return productOptions.value;
    });
  };
  const formattedNumber = (row, column, cellValue) => {
    return parseFloat(cellValue).toFixed(2);
  };
  // 获取tree子数据
  const getModels = value => {
    productForm.value.productCategory = findNodeById(productOptions.value, value);
    modelList({ id: value }).then(res => {
      modelOptions.value = res;
    });
  };
  const getProductModel = value => {
    const index = modelOptions.value.findIndex(item => item.id === value);
    if (index !== -1) {
      productForm.value.specificationModel = modelOptions.value[index].model;
      productForm.value.unit = modelOptions.value[index].unit;
    } else {
      productForm.value.specificationModel = null;
      productForm.value.unit = null;
    }
  };
  const findNodeById = (nodes, productId) => {
    for (let i = 0; i < nodes.length; i++) {
      if (nodes[i].value === productId) {
        return nodes[i].label; // 找到节点,返回该节点
      }
      if (nodes[i].children && nodes[i].children.length > 0) {
        const foundNode = findNodeById(nodes[i].children, productId);
        if (foundNode) {
          return foundNode; // 在子节点中找到,返回该节点
        }
      }
    }
    return null; // 没有找到节点,返回null
  };
  function convertIdToValue(data) {
    return data.map(item => {
      const { id, children, ...rest } = item;
      const newItem = {
        ...rest,
        value: id, // 将 id 改为 value
      };
      if (children && children.length > 0) {
        newItem.children = convertIdToValue(children);
      }
      return newItem;
    });
  }
  // 根据名称反查产品大类 id,便于仅存名称时的反显
  function findNodeIdByLabel(nodes, label) {
    if (!label) return null;
    for (let i = 0; i < nodes.length; i++) {
      const node = nodes[i];
      if (node.label === label) return node.value;
      if (node.children && node.children.length > 0) {
        const found = findNodeIdByLabel(node.children, label);
        if (found !== null && found !== undefined) return found;
      }
    }
    return null;
  }
  // 表格选择数据
  const handleSelectionChange = selection => {
    // 过滤掉子数据
    selectedRows.value = selection.filter(item => item.children !== undefined);
    console.log("selection", selectedRows.value);
  };
  const productSelected = selectedRows => {
    productSelectedRows.value = selectedRows;
  };
  const expandedRowKeys = ref([]);
  // 展开行
  const expandChange = (row, expandedRows) => {
    if (expandedRows.length > 0) {
      expandedRowKeys.value = [];
      try {
        productList({ salesLedgerId: row.id, type: 1 }).then(res => {
          const index = tableData.value.findIndex(item => item.id === row.id);
          if (index > -1) {
            // 为子表格数据添加客户类型信息
            const childrenData = res.data.map(item => ({
              ...item,
              customerType: row.customerType,
            }));
            tableData.value[index].children = childrenData;
          }
          expandedRowKeys.value.push(row.id);
        });
      } catch (error) {
        console.log(error);
      }
    } else {
      expandedRowKeys.value = [];
    }
  };
  // 添加表行类名方法
  const tableRowClassName = ({ row }) => {
    if (!row.deliveryDate) return "";
    if (row.isFh) return "";
    const diff = row.deliveryDaysDiff;
    if (diff === 15) {
      return "yellow";
    } else if (diff === 10) {
      return "pink";
    } else if (diff === 2) {
      return "purple";
    } else if (diff < 2) {
      return "red";
    }
  };
  // 主表合计方法
  const summarizeMainTable = param => {
    return proxy.summarizeTable(param, [
      "contractAmount",
      "taxInclusiveTotalPrice",
      "taxExclusiveTotalPrice",
    ]);
  };
  // 子表合计方法
  const summarizeChildrenTable = param => {
    return proxy.summarizeTable(param, [
      "taxInclusiveUnitPrice",
      "taxInclusiveTotalPrice",
      "taxExclusiveTotalPrice",
    ]);
  };
  // 客户选择变化处理
  const handleCustomerChange = customerId => {
    if (customerId) {
      const customer = customerOption.value.find(item => item.id === customerId);
      if (customer) {
        // 如果客户类型发生变化,清空表格数据
        if (
          currentCustomerType.value &&
          currentCustomerType.value !== customer.customerType
        ) {
          productData.value = [];
        }
        currentCustomerType.value = customer.customerType;
      }
    } else {
      currentCustomerType.value = "";
      productData.value = [];
    }
  };
  // 打开弹框
  const openForm = async (type, row) => {
    operationType.value = type;
    form.value = {};
    productData.value = [];
    selectedQuotation.value = null;
    currentCustomerType.value = "";
    let userLists = await userListNoPage();
    userList.value = userLists.data;
    customerList().then(res => {
      customerOption.value = res;
      // 如果是编辑模式且有客户ID,设置客户类型
      if (type === "edit" && form.value.customerId) {
        handleCustomerChange(form.value.customerId);
      }
    });
    form.value.entryPerson = userStore.id;
    if (type === "add") {
      // 新增时设置录入日期为当天
      form.value.entryDate = getCurrentDate();
      // 签订日期默认为当天
      form.value.executionDate = getCurrentDate();
    } else {
      currentId.value = row.id;
      getSalesLedgerWithProducts({ id: row.id, type: 1 }).then(res => {
        form.value = { ...res };
        form.value.entryPerson = Number(res.entryPerson);
        productData.value = JSON.parse(
          JSON.stringify(form.value.productData || [])
        );
        fileList.value = form.value.salesLedgerFiles
          ? form.value.salesLedgerFiles
          : [];
        // 设置客户类型
        handleCustomerChange(form.value.customerId);
      });
    }
    // let userAll = await userStore.getInfo()
    // userList.value.forEach(element => {
    //   if(userAll.user.nickName === element.nickName && userAll.user.userName === element.userName) {
    //     form.value.entryPerson = userAll.user.userId // 设置默认业务员为当前用户
    //   }
    // });
    form.value.entryDate = getCurrentDate(); // 设置默认录入日期为当前日期
    dialogFormVisible.value = true;
  };
  // 打开报价单选择弹窗(仅审批通过)
  const openQuotationDialog = async () => {
    if (operationType.value === "view") return;
    quotationDialogVisible.value = true;
    // 打开弹窗时重置分页到第一页
    quotationPage.current = 1;
    // 先确保客户列表已加载,便于后续回填 customerId
    if (!customerOption.value || customerOption.value.length === 0) {
      try {
        const res = await customerList();
        customerOption.value = res;
      } catch (e) {
        // ignore,允许用户后续手动选择客户
      }
    }
    await fetchQuotationList();
  };
  const fetchQuotationList = async () => {
    quotationLoading.value = true;
    try {
      const params = {
        // 后端分页字段:current / size
        current: quotationPage.current,
        size: quotationPage.size,
        ...quotationSearchForm,
        status: "通过",
      };
      const res = await getQuotationList(params);
      quotationList.value = res?.data?.records || [];
      quotationPage.total = res?.data?.total || 0;
    } finally {
      quotationLoading.value = false;
    }
  };
  const resetQuotationSearch = async () => {
    quotationSearchForm.quotationNo = "";
    quotationSearchForm.customer = "";
    quotationPage.current = 1;
    await fetchQuotationList();
  };
  // 报价单弹框分页切换
  const quotationPaginationChange = obj => {
    quotationPage.current = obj.page;
    quotationPage.size = obj.limit;
    fetchQuotationList();
  };
  // 选中报价单后回填到台账表单
  const applyQuotation = row => {
    if (!row) return;
    selectedQuotation.value = row;
    // 业务员
    form.value.salesman = (row.salesperson || "").trim();
    // 客户名称 -> customerId
    const qCustomerName = String(row.customer || "").trim();
    const customer = (customerOption.value || []).find(c => {
      const name = String(c.customerName || "").trim();
      return (
        name === qCustomerName ||
        name.includes(qCustomerName) ||
        qCustomerName.includes(name)
      );
    });
    if (customer?.id) {
      form.value.customerId = customer.id;
    } else {
      // 如果找不到,保留原值(允许用户手动选择/不打断已有输入)
      form.value.customerId = form.value.customerId || "";
    }
    // 产品信息映射:报价 products -> 台账 productData
    const products = Array.isArray(row.products) ? row.products : [];
    productData.value = products.map(p => {
      const quantity = Number(p.quantity ?? 0) || 0;
      const unitPrice = Number(p.unitPrice ?? 0) || 0;
      const taxRate = "13"; // 默认 13%,便于直接提交(如需可在产品中自行修改)
      const taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
      const taxExclusiveTotalPrice = proxy.calculateTaxExclusiveTotalPrice(
        taxInclusiveTotalPrice,
        taxRate
      );
      return {
        // 台账字段
        productCategory: p.product || p.productName || "",
        specificationModel: p.specification || "",
        unit: p.unit || "",
        quantity: quantity,
        taxRate: taxRate,
        taxInclusiveUnitPrice: unitPrice.toFixed(2),
        taxInclusiveTotalPrice: taxInclusiveTotalPrice,
        taxExclusiveTotalPrice: taxExclusiveTotalPrice,
        invoiceType: "增普票",
      };
    });
    quotationDialogVisible.value = false;
  };
  function changs(val) {
    console.log(val);
  }
  // 上传前校检
  function handleBeforeUpload(file) {
    // 校检文件大小
    // if (file.size > 1024 * 1024 * 10) {
    //   proxy.$modal.msgError("上传文件大小不能超过10MB!");
    //   return false;
    // }
    proxy.$modal.loading("正在上传文件,请稍候...");
    return true;
  }
  // 上传失败
  function handleUploadError(err) {
    proxy.$modal.msgError("上传文件失败");
    proxy.$modal.closeLoading();
  }
  // 上传成功回调
  function handleUploadSuccess(res, file, uploadFiles) {
    proxy.$modal.closeLoading();
    if (res.code === 200) {
      file.tempId = res.data.tempId;
      proxy.$modal.msgSuccess("上传成功");
    } else {
      proxy.$modal.msgError(res.msg);
      proxy.$refs.fileUpload.handleRemove(file);
    }
  }
  // 移除文件
  function handleRemove(file) {
    if (operationType.value === "edit") {
      let ids = [];
      ids.push(file.id);
      delLedgerFile(ids).then(res => {
        proxy.$modal.msgSuccess("删除成功");
      });
    }
  }
  // 提交表单
  const submitForm = () => {
    proxy.$refs["formRef"].validate(valid => {
      if (valid) {
        console.log("productData.value--", productData.value);
        if (productData.value !== null && productData.value.length > 0) {
          form.value.productData = proxy.HaveJson(productData.value);
        } else {
          proxy.$modal.msgWarning("请添加产品信息");
          return;
        }
        let tempFileIds = [];
        if (fileList.value !== null && fileList.value.length > 0) {
          tempFileIds = fileList.value.map(item => item.tempId);
        }
        form.value.tempFileIds = tempFileIds;
        form.value.type = 1;
        form.value.salesType = currentCustomerType.value;
        addOrUpdateSalesLedger(form.value).then(res => {
          proxy.$modal.msgSuccess("提交成功");
          closeDia();
          getList();
        });
      }
    });
  };
  // 关闭弹框
  const closeDia = () => {
    proxy.resetForm("formRef");
    dialogFormVisible.value = false;
  };
  const productIndex = ref(0);
  // 打开产品弹框
  const openProductForm = async (type, row, index) => {
    // 编辑时检查产品是否已发货或审核通过
    if (type === "edit" && isProductShipped(row)) {
      proxy.$modal.msgWarning("已发货或审核通过的产品不能编辑");
      return;
    }
    productOperationType.value = type;
    productForm.value = {};
    proxy.resetForm("productFormRef");
    if (type === "edit") {
      productForm.value = { ...row };
      productIndex.value = index;
      // 编辑时根据产品大类名称反查 tree 节点 id,并加载规格型号列表
      try {
        const options =
          productOptions.value && productOptions.value.length > 0
            ? productOptions.value
            : await getProductOptions();
        const categoryId = findNodeIdByLabel(
          options,
          productForm.value.productCategory
        );
        if (categoryId) {
          const models = await modelList({ id: categoryId });
          modelOptions.value = models || [];
          // 根据当前规格型号名称反查并设置 productModelId,便于下拉框显示已选值
          const currentModel = (modelOptions.value || []).find(
            m => m.model === productForm.value.specificationModel
          );
          if (currentModel) {
            productForm.value.productModelId = currentModel.id;
          }
        }
      } catch (e) {
        // 加载失败时保持可编辑,不中断弹窗
        console.error("加载产品规格型号失败", e);
      }
    } else {
      getProductOptions();
    }
    productFormVisible.value = true;
  };
  // 提交产品表单
  const submitProduct = () => {
    // 动态验证规则
    const dynamicRules = { ...productRules.value };
    // 根据客户类型调整验证规则
    if (currentCustomerType.value == 1) {
      // 对私字段不需要验证
      delete dynamicRules.unitPrice;
      delete dynamicRules.totalPrice;
      delete dynamicRules.freight;
      delete dynamicRules.priceWithFreight;
    } else if (currentCustomerType.value == 2) {
      // 对公字段不需要验证
      delete dynamicRules.taxInclusiveUnitPrice;
      delete dynamicRules.taxRate;
      delete dynamicRules.taxInclusiveTotalPrice;
      delete dynamicRules.taxExclusiveTotalPrice;
      delete dynamicRules.invoiceType;
    }
    proxy.$refs["productFormRef"].validate((valid, fields) => {
      if (valid) {
        if (operationType.value === "edit") {
          // 编辑模式下直接修改本地表格数据
          if (productOperationType.value === "add") {
            productData.value.push({ ...productForm.value });
          } else {
            productData.value.splice(productIndex.value, 1, {
              ...productForm.value,
            });
          }
          closeProductDia();
        } else {
          if (productOperationType.value === "add") {
            productData.value.push({ ...productForm.value });
          } else {
            productData.value.splice(productIndex.value, 1, {
              ...productForm.value,
            });
          }
          closeProductDia();
        }
      }
    });
  };
  const submitProductEdit = () => {
    // 根据客户类型调整提交的数据
    const productDataToSubmit = { ...productForm.value };
    if (currentCustomerType.value == 1) {
      // 对私字段不需要提交
      delete productDataToSubmit.unitPrice;
      delete productDataToSubmit.totalPrice;
      delete productDataToSubmit.freight;
      delete productDataToSubmit.priceWithFreight;
    } else if (currentCustomerType.value == 2) {
      // 对公字段不需要提交
      delete productDataToSubmit.taxInclusiveUnitPrice;
      delete productDataToSubmit.taxRate;
      delete productDataToSubmit.taxInclusiveTotalPrice;
      delete productDataToSubmit.taxExclusiveTotalPrice;
      delete productDataToSubmit.invoiceType;
    }
    productDataToSubmit.salesLedgerId = currentId.value;
    productDataToSubmit.type = 1;
    addOrUpdateSalesLedgerProduct(productDataToSubmit).then(res => {
      proxy.$modal.msgSuccess("提交成功");
      closeProductDia();
      getSalesLedgerWithProducts({ id: currentId.value, type: 1 }).then(res => {
        productData.value = JSON.parse(JSON.stringify(res.productData || []));
      });
    });
  };
  // 删除产品
  const deleteProduct = () => {
    if (productSelectedRows.value.length === 0) {
      proxy.$modal.msgWarning("请选择数据");
      return;
    }
    // 检查是否有已发货或审核通过的产品
    const shippedProducts = productSelectedRows.value.filter(row =>
      isProductShipped(row)
    );
    if (shippedProducts.length > 0) {
      proxy.$modal.msgWarning("已发货或审核通过的产品不能删除");
      return;
    }
    // 无论是新增还是编辑模式,都直接修改本地表格数据
    productSelectedRows.value.forEach(selectedRow => {
      const index = productData.value.findIndex(
        product => product.id === selectedRow.id
      );
      if (index !== -1) {
        productData.value.splice(index, 1);
      }
    });
  };
  // 关闭产品弹框
  const closeProductDia = () => {
    proxy.resetForm("productFormRef");
    productFormVisible.value = false;
  };
  // 导入
  const handleImport = () => {
    importUpload.title = "导入销售台账";
    importUpload.open = true;
    if (importUploadRef.value) {
      importUploadRef.value.clearFiles();
    }
  };
  // 下载导入模板
  const downloadTemplate = () => {
    proxy.download("/sales/ledger/exportTemplate", {}, "销售台账导入模板.xlsx");
  };
  // 提交导入文件
  const submitImportFile = () => {
    importUpload.isUploading = true;
    proxy.$refs["importUploadRef"].submit();
  };
  // 导出
  const handleOut = () => {
    ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
      confirmButtonText: "确认",
      cancelButtonText: "取消",
      type: "warning",
    })
      .then(() => {
        proxy.download("/sales/ledger/export", {}, "销售台账.xlsx");
      })
      .catch(() => {
        proxy.$modal.msg("已取消");
      });
  };
  /** 判断单个产品是否已发货(根据shippingStatus判断,已发货或审核通过不可编辑和删除) */
  const isProductShipped = product => {
    if (!product) return false;
    const status = String(product.shippingStatus || "").trim();
    // 如果发货状态是"已发货"或"审核通过",则不可编辑和删除
    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 === "已发货"
      );
    });
  };
  // 删除
  const handleDelete = async () => {
    if (selectedRows.value.length === 0) {
      proxy.$modal.msgWarning("请选择数据");
      return;
    }
    const ids = selectedRows.value.map(item => item.id);
    // 检查是否有已进行发货或发货完成的销售订单,若有则不允许删除
    const cannotDeleteNames = [];
    for (const row of selectedRows.value) {
      let products =
        row.children && row.children.length > 0 ? row.children : null;
      if (!products) {
        try {
          const res = await productList({ salesLedgerId: row.id, type: 1 });
          products = res.data || [];
        } catch {
          products = [];
        }
      }
      if (hasShippedProducts(products)) {
        cannotDeleteNames.push(row.salesContractNo || `ID:${row.id}`);
      }
    }
    if (cannotDeleteNames.length > 0) {
      proxy.$modal.msgWarning(
        "已进行发货或发货完成的销售订单不能删除:" + cannotDeleteNames.join("、")
      );
      return;
    }
    ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "导出", {
      confirmButtonText: "确认",
      cancelButtonText: "取消",
      type: "warning",
    })
      .then(() => {
        delLedger(ids).then(res => {
          proxy.$modal.msgSuccess("删除成功");
          getList();
        });
      })
      .catch(() => {
        proxy.$modal.msg("已取消");
      });
  };
  // 打印功能
  const handlePrint = async () => {
    if (selectedRows.value.length === 0) {
      proxy.$modal.msgWarning("请选择要打印的数据");
      return;
    }
    // 显示加载状态
    proxy.$modal.loading("正在获取产品数据,请稍候...");
    try {
      // 为每个选中的销售台账记录查询对应的产品数据
      const printDataWithProducts = [];
      for (const row of selectedRows.value) {
        try {
          // 调用productList接口查询产品数据
          const productRes = await productList({
            salesLedgerId: row.id,
            type: 1,
          });
          // 将产品数据整合到销售台账记录中
          const rowWithProducts = {
            ...row,
            products: productRes.data || [],
          };
          printDataWithProducts.push(rowWithProducts);
        } catch (error) {
          console.error(`获取销售台账 ${row.id} 的产品数据失败:`, error);
          // 即使某个记录的产品数据获取失败,也要包含该记录
          printDataWithProducts.push({
            ...row,
            products: [],
          });
        }
      }
      printData.value = printDataWithProducts;
      console.log("打印数据(包含产品):", printData.value);
      printPreviewVisible.value = true;
    } catch (error) {
      console.error("获取产品数据失败:", error);
      proxy.$modal.msgError("获取产品数据失败,请重试");
    } finally {
      proxy.$modal.closeLoading();
    }
  };
  // 执行打印
  const executePrint = () => {
    console.log("开始执行打印,数据条数:", printData.value.length);
    console.log("打印数据:", printData.value);
    // 创建一个新的打印窗口
    const printWindow = window.open("", "_blank", "width=800,height=600");
    // 构建打印内容
    let printContent = `
                                                                                                                                                                                                                                                                      <!DOCTYPE html>
                                                                                                                                                                                                                                                                      <html>
                                                                                                                                                                                                                                                                      <head>
                                                                                                                                                                                                                                                                        <meta charset="UTF-8">
                                                                                                                                                                                                                                                                        <title>打印预览</title>
                                                                                                                                                                                                                                                                        <style>
                                                                                                                                                                                                                                                                          body {
                                                                                                                                                                                                                                                                            margin: 0;
                                                                                                                                                                                                                                                                            padding: 0;
                                                                                                                                                                                                                                                                            font-family: "SimSun", serif;
                                                                                                                                                                                                                                                                            background: white;
                                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                                                                                       .print-page {
                                                                                                                                                                                                                                                                              width: 200mm;
                                                                                                                                                                                                                                                                              height: 75mm;
                                                                                                                                                                                                                                                                              padding: 10mm;
                                                                                                                                                                                                                                                                              padding-left: 20mm;
                                                                                                                                                                                                                                                                              background: white;
                                                                                                                                                                                                                                                                              box-sizing: border-box;
                                                                                                                                                                                                                                                                              page-break-after: always;
                                                                                                                                                                                                                                                                              page-break-inside: avoid;
                                                                                                                                                                                                                                                                            }
                                                                                                                                                                                                                                                                           .print-page:last-child {
                                                                                                                                                                                                                                                                             page-break-after: avoid;
                                                                                                                                                                                                                                                                           }
                                                                                                                                                                                                                                                                          .delivery-note {
                                                                                                                                                                                                                                                                            width: 100%;
                                                                                                                                                                                                                                                                            height: 100%;
                                                                                                                                                                                                                                                                            font-size: 12px;
                                                                                                                                                                                                                                                                            line-height: 1.2;
                                                                                                                                                                                                                                                                            display: flex;
                                                                                                                                                                                                                                                                            flex-direction: column;
                                                                                                                                                                                                                                                                            color: #000;
                                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                                          .header {
                                                                                                                                                                                                                                                                            text-align: center;
                                                                                                                                                                                                                                                                            margin-bottom: 8px;
                                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                                          .company-name {
                                                                                                                                                                                                                                                                            font-size: 18px;
                                                                                                                                                                                                                                                                            font-weight: bold;
                                                                                                                                                                                                                                                                            margin-bottom: 4px;
                                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                                          .document-title {
                                                                                                                                                                                                                                                                            font-size: 16px;
                                                                                                                                                                                                                                                                            font-weight: bold;
                                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                                          .info-section {
                                                                                                                                                                                                                                                                            margin-bottom: 8px;
                                                                                                                                                                                                                                                                            display: flex;
                                                                                                                                                                                                                                                                            justify-content: space-between;
                                                                                                                                                                                                                                                                            align-items: center;
                                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                                          .info-row {
                                                                                                                                                                                                                                                                            line-height: 20px;
                                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                                          .label {
                                                                                                                                                                                                                                                                            font-weight: bold;
                                                                                                                                                                                                                                                                            width: 60px;
                                                                                                                                                                                                                                                                            font-size: 12px;
                                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                                          .value {
                                                                                                                                                                                                                                                                            margin-right: 20px;
                                                                                                                                                                                                                                                                            min-width: 80px;
                                                                                                                                                                                                                                                                            font-size: 12px;
                                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                                                   .table-section {
                                                                                                                                                                                                                                                                                   margin-bottom: 40px;
                                                                                                                                                                                                                                                                            //  flex: 0.6;
                                                                                                                                                                                                                                                                           }
                                                                                                                                                                                                                                                                          .product-table {
                                                                                                                                                                                                                                                                            width: 100%;
                                                                                                                                                                                                                                                                            border-collapse: collapse;
                                                                                                                                                                                                                                                                            border: 1px solid #000;
                                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                                                   .product-table th, .product-table td {
                                                                                                                                                                                                                                                                             border: 1px solid #000;
                                                                                                                                                                                                                                                                             padding: 6px;
                                                                                                                                                                                                                                                                             text-align: center;
                                                                                                                                                                                                                                                                             font-size: 12px;
                                                                                                                                                                                                                                                                             line-height: 1.4;
                                                                                                                                                                                                                                                                           }
                                                                                                                                                                                                                                                                          .product-table th {
                                                                                                                                                                                                                                                                            font-weight: bold;
                                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                                          .total-value {
                                                                                                                                                                                                                                                                            font-weight: bold;
                                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                                          .footer-section {
                                                                                                                                                                                                                                                                            margin-top: auto;
                                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                                          .footer-row {
                                                                                                                                                                                                                                                                            display: flex;
                                                                                                                                                                                                                                                                            margin-bottom: 3px;
                                                                                                                                                                                                                                                                            line-height: 22px;
                                                                                                                                                                                                                                                                            justify-content: space-between;
                                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                                          .footer-item {
                                                                                                                                                                                                                                                                            display: flex;
                                                                                                                                                                                                                                                                            margin-right: 20px;
                                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                                          .footer-item .label {
                                                                                                                                                                                                                                                                            font-weight: bold;
                                                                                                                                                                                                                                                                            width: 80px;
                                                                                                                                                                                                                                                                            font-size: 12px;
                                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                                          .footer-item .value {
                                                                                                                                                                                                                                                                            min-width: 80px;
                                                                                                                                                                                                                                                                            font-size: 12px;
                                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                                          .address-item .address-value {
                                                                                                                                                                                                                                                                            min-width: 200px;
                                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                                          @media print {
                                                                                                                                                                                                                                                                            body {
                                                                                                                                                                                                                                                                              margin: 0;
                                                                                                                                                                                                                                                                              padding: 0;
                                                                                                                                                                                                                                                                            }
                                                                                                                                                                                                                                                                                       .print-page {
                                                                                                                                                                                                                                                                               margin: 0;
                                                                                                                                                                                                                                                                               padding: 10mm;
                                                                                                                                                                                                                                                                               /* padding-left: 20mm; */
                                                                                                                                                                                                                                                                               page-break-inside: avoid;
                                                                                                                                                                                                                                                                               page-break-after: always;
                                                                                                                                                                                                                                                                             }
                                                                                                                                                                                                                                                                             .print-page:last-child {
                                                                                                                                                                                                                                                                               page-break-after: avoid;
                                                                                                                                                                                                                                                                             }
                                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                                        </style>
                                                                                                                                                                                                                                                                      </head>
                                                                                                                                                                                                                                                                      <body>
                                                                                                                                                                                                                                                                    `;
    // 为每条数据生成打印页面
    printData.value.forEach((item, index) => {
      printContent += `
                                                                                                                                                                                                                                                                        <div class="print-page">
                                                                                                                                                                                                                                                                          <div class="delivery-note">
                                                                                                                                                                                                                                                                            <div class="header">
                                                                                                                                                                                                                                                                              <div class="document-title">零售发货单</div>
                                                                                                                                                                                                                                                                            </div>
                                                                                                                                                                                                                                                                            <div class="info-section">
                                                                                                                                                                                                                                                                              <div class="info-row">
                                                                                                                                                                                                                                                                                <div>
                                                                                                                                                                                                                                                                                  <span class="label">发货日期:</span>
                                                                                                                                                                                                                                                                                  <span class="value">${formatDate(
                                                                                                                                                                                                                                                                                    item.createTime
                                                                                                                                                                                                                                                                                  )}</span>
                                                                                                                                                                                                                                                                                </div>
                                                                                                                                                                                                                                                                                <div>
                                                                                                                                                                                                                                                                                  <span class="label">客户名称:</span>
                                                                                                                                                                                                                                                                                  <span class="value">${
                                                                                                                                                                                                                                                                                    item.customerName
                                                                                                                                                                                                                                                                                  }</span>
                                                                                                                                                                                                                                                                                </div>
                                                                                                                                                                                                                                                                              </div>
                                                                                                                                                                                                                                                                              <div class="info-row">
                                                                                                                                                                                                                                                                                <span class="label">单号:</span>
                                                                                                                                                                                                                                                                                <span class="value">${
                                                                                                                                                                                                                                                                                  item.salesContractNo ||
                                                                                                                                                                                                                                                                                  ""
                                                                                                                                                                                                                                                                                }</span>
                                                                                                                                                                                                                                                                              </div>
                                                                                                                                                                                                                                                                            </div>
                                                                                                                                                                                                                                                                            <div class="table-section">
                                                                                                                                                                                                                                                                              <table class="product-table">
                                                                                                                                                                                                                                                                                <thead>
                                                                                                                                                                                                                                                                                  <tr>
                                                                                                                                                                                                                                                                                    <th>产品名称</th>
                                                                                                                                                                                                                                                                                    <th>规格型号</th>
                                                                                                                                                                                                                                                                                    <th>单位</th>
                                                                                                                                                                                                                                                                                    <th>单价</th>
                                                                                                                                                                                                                                                                                    <th>零售数量</th>
                                                                                                                                                                                                                                                                                    <th>零售金额</th>
                                                                                                                                                                                                                                                                                  </tr>
                                                                                                                                                                                                                                                                                </thead>
                                                                                                                                                                                                                                                                                <tbody>
                                                                                                                                                                                                                                                                                  ${
                                                                                                                                                                                                                                                                                    item.products &&
                                                                                                                                                                                                                                                                                    item
                                                                                                                                                                                                                                                                                      .products
                                                                                                                                                                                                                                                                                      .length >
                                                                                                                                                                                                                                                                                      0
                                                                                                                                                                                                                                                                                      ? item.products
                                                                                                                                                                                                                                                                                          .map(
                                                                                                                                                                                                                                                                                            product => `
                                                                                                                                                                                                                                                                                      <tr>
                                                                                                                                                                                                                                                                                        <td>${
                                                                                                                                                                                                                                                                                          product.productCategory ||
                                                                                                                                                                                                                                                                                          ""
                                                                                                                                                                                                                                                                                        }</td>
                                                                                                                                                                                                                                                                                        <td>${
                                                                                                                                                                                                                                                                                          product.specificationModel ||
                                                                                                                                                                                                                                                                                          ""
                                                                                                                                                                                                                                                                                        }</td>
                                                                                                                                                                                                                                                                                        <td>${
                                                                                                                                                                                                                                                                                          product.unit ||
                                                                                                                                                                                                                                                                                          ""
                                                                                                                                                                                                                                                                                        }</td>
                                                                                                                                                                                                                                                                                        <td>${
                                                                                                                                                                                                                                                                                          product.taxInclusiveUnitPrice ||
                                                                                                                                                                                                                                                                                          "0"
                                                                                                                                                                                                                                                                                        }</td>
                                                                                                                                                                                                                                                                                        <td>${
                                                                                                                                                                                                                                                                                          product.quantity ||
                                                                                                                                                                                                                                                                                          "0"
                                                                                                                                                                                                                                                                                        }</td>
                                                                                                                                                                                                                                                                                        <td>${
                                                                                                                                                                                                                                                                                          product.taxInclusiveTotalPrice ||
                                                                                                                                                                                                                                                                                          "0"
                                                                                                                                                                                                                                                                                        }</td>
                                                                                                                                                                                                                                                                                      </tr>
                                                                                                                                                                                                                                                                                    `
                                                                                                                                                                                                                                                                                          )
                                                                                                                                                                                                                                                                                          .join(
                                                                                                                                                                                                                                                                                            ""
                                                                                                                                                                                                                                                                                          )
                                                                                                                                                                                                                                                                                      : '<tr><td colspan="6" style="text-align: center; color: #999;">暂无产品数据</td></tr>'
                                                                                                                                                                                                                                                                                  }
                                                                                                                                                                                                                                                                                </tbody>
                                                                                                                                                                                                                                                                                <tfoot>
                                                                                                                                                                                                                                                                                  <tr>
                                                                                                                                                                                                                                                                                    <td class="label">合计</td>
                                                                                                                                                                                                                                                                                    <td class="total-value"></td>
                                                                                                                                                                                                                                                                                    <td class="total-value"></td>
                                                                                                                                                                                                                                                                                    <td class="total-value"></td>
                                                                                                                                                                                                                                                                                    <td class="total-value">${getTotalQuantityForPrint(
                                                                                                                                                                                                                                                                                      item.products
                                                                                                                                                                                                                                                                                    )}</td>
                                                                                                                                                                                                                                                                                    <td class="total-value">${getTotalAmountForPrint(
                                                                                                                                                                                                                                                                                      item.products
                                                                                                                                                                                                                                                                                    )}</td>
                                                                                                                                                                                                                                                                                  </tr>
                                                                                                                                                                                                                                                                                </tfoot>
                                                                                                                                                                                                                                                                              </table>
                                                                                                                                                                                                                                                                            </div>
                                                                                                                                                                                                                                                                            <div class="footer-section">
                                                                                                                                                                                                                                                                              <div class="footer-row">
                                                                                                                                                                                                                                                                                <div class="footer-item">
                                                                                                                                                                                                                                                                                  <span class="label">收货电话:</span>
                                                                                                                                                                                                                                                                                  <span class="value"></span>
                                                                                                                                                                                                                                                                                </div>
                                                                                                                                                                                                                                                                                <div class="footer-item">
                                                                                                                                                                                                                                                                                  <span class="label">收货人:</span>
                                                                                                                                                                                                                                                                                  <span class="value"></span>
                                                                                                                                                                                                                                                                                </div>
                                                                                                                                                                                                                                                                                <div class="footer-item address-item">
                                                                                                                                                                                                                                                                                  <span class="label">收货地址:</span>
                                                                                                                                                                                                                                                                                  <span class="value address-value"></span>
                                                                                                                                                                                                                                                                                </div>
                                                                                                                                                                                                                                                                              </div>
                                                                                                                                                                                                                                                                              <div class="footer-row">
                                                                                                                                                                                                                                                                                <div class="footer-item">
                                                                                                                                                                                                                                                                                  <span class="label">操作员:</span>
                                                                                                                                                                                                                                                                                  <span class="value">${
                                                                                                                                                                                                                                                                                    userStore.nickName ||
                                                                                                                                                                                                                                                                                    "撕开前"
                                                                                                                                                                                                                                                                                  }</span>
                                                                                                                                                                                                                                                                                </div>
                                                                                                                                                                                                                                                                                <div class="footer-item">
                                                                                                                                                                                                                                                                                  <span class="label">打印日期:</span>
                                                                                                                                                                                                                                                                                  <span class="value">${formatDateTime(
                                                                                                                                                                                                                                                                                    new Date()
                                                                                                                                                                                                                                                                                  )}</span>
                                                                                                                                                                                                                                                                                </div>
                                                                                                                                                                                                                                                                              </div>
                                                                                                                                                                                                                                                                            </div>
                                                                                                                                                                                                                                                                          </div>
                                                                                                                                                                                                                                                                        </div>
                                                                                                                                                                                                                                                                      `;
    });
    printContent += `
                                                                                                                                                                                                                                                                      </body>
                                                                                                                                                                                                                                                                      </html>
                                                                                                                                                                                                                                                                    `;
    // 写入内容到新窗口
    printWindow.document.write(printContent);
    printWindow.document.close();
    // 等待内容加载完成后打印
    printWindow.onload = () => {
      setTimeout(() => {
        printWindow.print();
        printWindow.close();
        printPreviewVisible.value = false;
      }, 500);
    };
  };
  // 格式化日期
  const formatDate = dateString => {
    if (!dateString) return getCurrentDate();
    const date = new Date(dateString);
    const year = date.getFullYear();
    const month = String(date.getMonth() + 1).padStart(2, "0");
    const day = String(date.getDate()).padStart(2, "0");
    return `${year}/${month}/${day}`;
  };
  // 格式化日期时间
  const formatDateTime = date => {
    const year = date.getFullYear();
    const month = String(date.getMonth() + 1).padStart(2, "0");
    const day = String(date.getDate()).padStart(2, "0");
    const hours = String(date.getHours()).padStart(2, "0");
    const minutes = String(date.getMinutes()).padStart(2, "0");
    const seconds = String(date.getSeconds()).padStart(2, "0");
    return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`;
  };
  // 计算产品总数量
  const getTotalQuantity = products => {
    if (!products || products.length === 0) return "0";
    const total = products.reduce((sum, product) => {
      return sum + (parseFloat(product.quantity) || 0);
    }, 0);
    return total.toFixed(2);
  };
  // 计算产品总金额
  const getTotalAmount = products => {
    if (!products || products.length === 0) return "0";
    const total = products.reduce((sum, product) => {
      return sum + (parseFloat(product.taxInclusiveTotalPrice) || 0);
    }, 0);
    return total.toFixed(2);
  };
  // 用于打印的计算函数
  const getTotalQuantityForPrint = products => {
    if (!products || products.length === 0) return "0";
    const total = products.reduce((sum, product) => {
      return sum + (parseFloat(product.quantity) || 0);
    }, 0);
    return total.toFixed(2);
  };
  const getTotalAmountForPrint = products => {
    if (!products || products.length === 0) return "0";
    const total = products.reduce((sum, product) => {
      return sum + (parseFloat(product.taxInclusiveTotalPrice) || 0);
    }, 0);
    return total.toFixed(2);
  };
  const mathNum = () => {
    console.log("productForm.value", productForm.value);
    if (!productForm.value.taxInclusiveUnitPrice) {
      return;
    }
    if (!productForm.value.quantity) {
      return;
    }
    // 含税总价计算
    productForm.value.taxInclusiveTotalPrice =
      proxy.calculateTaxIncludeTotalPrice(
        productForm.value.taxInclusiveUnitPrice,
        productForm.value.quantity
      );
    if (productForm.value.taxRate) {
      // 不含税总价计算
      productForm.value.taxExclusiveTotalPrice =
        proxy.calculateTaxExclusiveTotalPrice(
          productForm.value.taxInclusiveTotalPrice,
          productForm.value.taxRate
        );
    }
  };
  // 根据含税总价计算含税单价和数量
  const calculateFromTotalPrice = () => {
    if (isCalculating.value) return;
    const totalPrice = parseFloat(productForm.value.taxInclusiveTotalPrice);
    const quantity = parseFloat(productForm.value.quantity);
    if (!totalPrice || !quantity || quantity <= 0) {
      return;
    }
    isCalculating.value = true;
    // 计算含税单价 = 含税总价 / 数量
    productForm.value.taxInclusiveUnitPrice = (totalPrice / quantity).toFixed(2);
    // 如果有税率,计算不含税总价
    if (productForm.value.taxRate) {
      productForm.value.taxExclusiveTotalPrice =
        proxy.calculateTaxExclusiveTotalPrice(
          totalPrice,
          productForm.value.taxRate
        );
    }
    isCalculating.value = false;
  };
  // 根据不含税总价计算含税单价和数量
  const calculateFromExclusiveTotalPrice = () => {
    if (!productForm.value.taxRate) {
      proxy.$modal.msgWarning("请先选择税率");
      return;
    }
    if (isCalculating.value) return;
    const exclusiveTotalPrice = parseFloat(
      productForm.value.taxExclusiveTotalPrice
    );
    const quantity = parseFloat(productForm.value.quantity);
    const taxRate = parseFloat(productForm.value.taxRate);
    if (!exclusiveTotalPrice || !quantity || quantity <= 0 || !taxRate) {
      return;
    }
    isCalculating.value = true;
    // 先计算含税总价 = 不含税总价 / (1 - 税率/100)
    const taxRateDecimal = taxRate / 100;
    const inclusiveTotalPrice = exclusiveTotalPrice / (1 - taxRateDecimal);
    productForm.value.taxInclusiveTotalPrice = inclusiveTotalPrice.toFixed(2);
    // 计算含税单价 = 含税总价 / 数量
    productForm.value.taxInclusiveUnitPrice = (
      inclusiveTotalPrice / quantity
    ).toFixed(2);
    isCalculating.value = false;
  };
  // 对私客户价格计算:单价和运费变化时计算含运费单价和总价
  const calculatePrivatePrice = () => {
    if (currentCustomerType.value == 2) {
      const unitPrice = parseFloat(productForm.value.unitPrice) || 0;
      const freight = parseFloat(productForm.value.freight) || 0;
      const quantity = parseFloat(productForm.value.quantity) || 0;
      // 计算含运费单价
      productForm.value.priceWithFreight = (unitPrice + freight).toFixed(2);
      // 计算总价
      productForm.value.totalPrice = (
        parseFloat(productForm.value.priceWithFreight) * quantity
      ).toFixed(2);
    }
  };
  // 对私客户价格计算:含运费单价变化时计算总价
  const calculatePrivateTotal = () => {
    if (currentCustomerType.value == 2) {
      const priceWithFreight =
        parseFloat(productForm.value.priceWithFreight) || 0;
      const quantity = parseFloat(productForm.value.quantity) || 0;
      // 计算总价
      productForm.value.totalPrice = (priceWithFreight * quantity).toFixed(2);
    }
  };
  // 根据数量变化计算总价
  const calculateFromQuantity = () => {
    // 对私客户使用对私计算逻辑
    if (currentCustomerType.value == 2) {
      calculatePrivatePrice();
      return;
    }
    // 对公客户使用原有的计算逻辑
    if (!productForm.value.taxRate) {
      proxy.$modal.msgWarning("请先选择税率");
      return;
    }
    if (isCalculating.value) return;
    const quantity = parseFloat(productForm.value.quantity);
    const unitPrice = parseFloat(productForm.value.taxInclusiveUnitPrice);
    if (!quantity || quantity <= 0 || !unitPrice) {
      return;
    }
    isCalculating.value = true;
    // 计算含税总价
    productForm.value.taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
    // 如果有税率,计算不含税总价
    if (productForm.value.taxRate) {
      productForm.value.taxExclusiveTotalPrice =
        proxy.calculateTaxExclusiveTotalPrice(
          productForm.value.taxInclusiveTotalPrice,
          productForm.value.taxRate
        );
    }
    isCalculating.value = false;
  };
  // 根据含税单价变化计算总价
  const calculateFromUnitPrice = () => {
    // 对私客户使用对私计算逻辑
    if (currentCustomerType.value == 2) {
      calculatePrivatePrice();
      return;
    }
    // 对公客户使用原有的计算逻辑
    if (!productForm.value.taxRate) {
      proxy.$modal.msgWarning("请先选择税率");
      return;
    }
    if (isCalculating.value) return;
    const quantity = parseFloat(productForm.value.quantity);
    const unitPrice = parseFloat(productForm.value.taxInclusiveUnitPrice);
    if (!quantity || quantity <= 0 || !unitPrice) {
      return;
    }
    isCalculating.value = true;
    // 计算含税总价
    productForm.value.taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
    // 如果有税率,计算不含税总价
    if (productForm.value.taxRate) {
      productForm.value.taxExclusiveTotalPrice =
        proxy.calculateTaxExclusiveTotalPrice(
          productForm.value.taxInclusiveTotalPrice,
          productForm.value.taxRate
        );
    }
    isCalculating.value = false;
  };
  // 根据税率变化计算不含税总价
  const calculateFromTaxRate = () => {
    // 对私客户不需要税率计算
    if (currentCustomerType.value == 2) {
      return;
    }
    // 对公客户使用原有的计算逻辑
    if (!productForm.value.taxRate) {
      proxy.$modal.msgWarning("请先选择税率");
      return;
    }
    if (isCalculating.value) return;
    const inclusiveTotalPrice = parseFloat(
      productForm.value.taxInclusiveTotalPrice
    );
    const taxRate = parseFloat(productForm.value.taxRate);
    if (!inclusiveTotalPrice || !taxRate) {
      return;
    }
    isCalculating.value = true;
    // 计算不含税总价
    productForm.value.taxExclusiveTotalPrice =
      proxy.calculateTaxExclusiveTotalPrice(inclusiveTotalPrice, taxRate);
    isCalculating.value = false;
  };
  /**
   * 获取发货状态文本
   * @param row 行数据
   */
  const getShippingStatusText = row => {
    // 如果已发货(有发货日期或车牌号),显示"已发货"
    if (row.shippingDate || row.shippingCarNumber) {
      return "已发货";
    }
    // 获取发货状态字段
    const status = row.shippingStatus;
    // 如果状态为空或未定义,默认为"待发货"
    if (status === null || status === undefined || status === "") {
      return "待发货";
    }
    // 状态是字符串
    const statusStr = String(status).trim();
    const statusTextMap = {
      待发货: "待发货",
      待审核: "待审核",
      审核中: "审核中",
      审核拒绝: "审核拒绝",
      审核通过: "审核通过",
      已发货: "已发货",
    };
    return statusTextMap[statusStr] || "待发货";
  };
  /**
   * 获取发货状态标签类型(颜色)
   * @param row 行数据
   */
  const getShippingStatusType = row => {
    // 如果已发货(有发货日期或车牌号),显示绿色
    if (row.shippingDate || row.shippingCarNumber) {
      return "success";
    }
    // 获取发货状态字段
    const status = row.shippingStatus;
    // 如果状态为空或未定义,默认为灰色(待发货)
    if (status === null || status === undefined || status === "") {
      return "info";
    }
    // 状态是字符串
    const statusStr = String(status).trim();
    const typeTextMap = {
      待发货: "info",
      待审核: "info",
      审核中: "warning",
      审核拒绝: "danger",
      审核通过: "success",
      已发货: "success",
    };
    return typeTextMap[statusStr] || "info";
  };
  /**
   * 判断是否可以发货
   * 只有在产品状态是充足,发货状态是待发货和审核拒绝的时候才可以发货
   * @param row 行数据
   */
  const canShip = row => {
    // 产品状态必须是充足(approveStatus === 1)
    if (row.approveStatus !== 1) {
      return false;
    }
    // 获取发货状态
    const shippingStatus = row.shippingStatus;
    // 如果已发货(有发货日期或车牌号),不能再次发货
    if (row.shippingDate || row.shippingCarNumber) {
      return false;
    }
    // 发货状态必须是"待发货"或"审核拒绝"
    const statusStr = shippingStatus ? String(shippingStatus).trim() : "";
    return statusStr === "待发货" || statusStr === "审核拒绝";
  };
  /**
   * 下载文件
   *
   * @param row 下载文件的相关信息对象
   */
  const fileListRef = ref(null);
  const fileListDialogVisible = ref(false);
  const downLoadFile = row => {
    getSalesLedgerWithProducts({ id: row.id, type: 1 }).then(res => {
      if (fileListRef.value) {
        fileListRef.value.open(res.salesLedgerFiles);
      }
    });
  };
  // 打开发货弹框
  const openDeliveryForm = row => {
    // 检查是否可以发货
    if (!canShip(row)) {
      proxy.$modal.msgWarning(
        "只有在产品状态是充足,发货状态是待发货或审核拒绝的时候才可以发货"
      );
      return;
    }
    currentDeliveryRow.value = row;
    deliveryForm.value = {
      type: "货车",
    };
    // 重置审批人节点(默认一个空节点)
    approverNodes.value = [{ id: 1, userId: null }];
    nextApproverId = 2;
    deliveryFormVisible.value = true;
  };
  // 提交发货表单
  const submitDelivery = () => {
    proxy.$refs["deliveryFormRef"].validate(valid => {
      if (valid) {
        // 审批人必填校验(所有节点都要选人)
        const hasEmptyApprover = approverNodes.value.some(node => !node.userId);
        if (hasEmptyApprover) {
          proxy.$modal.msgError("请为所有审批节点选择审批人!");
          return;
        }
        const approveUserIds = approverNodes.value
          .map(node => node.userId)
          .join(",");
        // 保存当前展开的行ID,以便发货后重新加载子表格数据
        const currentExpandedKeys = [...expandedRowKeys.value];
        const salesLedgerId = currentDeliveryRow.value.salesLedgerId;
        addShippingInfo({
          salesLedgerId: salesLedgerId,
          salesLedgerProductId: currentDeliveryRow.value.id,
          type: deliveryForm.value.type,
          approveUserIds,
        }).then(() => {
          proxy.$modal.msgSuccess("发货成功");
          closeDeliveryDia();
          // 刷新主表数据
@@ -2149,12 +2759,16 @@
            if (currentExpandedKeys.length > 0) {
              // 使用 Promise.all 并行加载所有展开行的子表格数据
              const loadPromises = currentExpandedKeys.map(ledgerId => {
                return productList({ salesLedgerId: ledgerId, type: 1 }).then((res) => {
                  const index = tableData.value.findIndex((item) => item.id === ledgerId);
                  if (index > -1) {
                    tableData.value[index].children = res.data;
                return productList({ salesLedgerId: ledgerId, type: 1 }).then(
                  res => {
                    const index = tableData.value.findIndex(
                      item => item.id === ledgerId
                    );
                    if (index > -1) {
                      tableData.value[index].children = res.data;
                    }
                  }
                });
                );
              });
              Promise.all(loadPromises).then(() => {
                // 恢复展开状态
@@ -2162,225 +2776,226 @@
              });
            }
          });
        })
    }
  });
};
        });
      }
    });
  };
// 关闭发货弹框
const closeDeliveryDia = () => {
  proxy.resetForm("deliveryFormRef");
  deliveryFormVisible.value = false;
  currentDeliveryRow.value = null;
};
const currentFactoryName = ref("");
const getCurrentFactoryName = async () => {
   let res = await userStore.getInfo();
   currentFactoryName.value = res.user.currentFactoryName;
};
onMounted(() => {
   getList();
   userListNoPage().then(res => {
      userList.value = res.data;
   })
   getCurrentFactoryName();
});
  // 关闭发货弹框
  const closeDeliveryDia = () => {
    proxy.resetForm("deliveryFormRef");
    deliveryFormVisible.value = false;
    currentDeliveryRow.value = null;
  };
  const currentFactoryName = ref("");
  const getCurrentFactoryName = async () => {
    let res = await userStore.getInfo();
    currentFactoryName.value = res.user.currentFactoryName;
  };
  onMounted(() => {
    getList();
    userListNoPage().then(res => {
      userList.value = res.data;
    });
    getCurrentFactoryName();
  });
</script>
<style scoped lang="scss">
.ml-10 {
   margin-left: 10px;
}
  .ml-10 {
    margin-left: 10px;
  }
::v-deep .yellow {
  background-color: #FAF0DE;
}
  ::v-deep .yellow {
    background-color: #faf0de;
  }
::v-deep .pink {
  background-color: #FAE1DE;
}
  ::v-deep .pink {
    background-color: #fae1de;
  }
::v-deep .red {
  background-color: #FAE1DE;
}
  ::v-deep .red {
    background-color: #fae1de;
  }
::v-deep .purple{
  background-color: #F4DEFA;
}
  ::v-deep .purple {
    background-color: #f4defa;
  }
.table_list {
   margin-top: unset;
}
  .table_list {
    margin-top: unset;
  }
.actions {
   display: flex;
   justify-content: space-between;
   margin-bottom: 10px;
}
.print-preview-dialog {
   .el-dialog__body {
      padding: 0;
      max-height: 80vh;
      overflow-y: auto;
   }
}
  .actions {
    display: flex;
    justify-content: space-between;
    margin-bottom: 10px;
  }
  .print-preview-dialog {
    .el-dialog__body {
      padding: 0;
      max-height: 80vh;
      overflow-y: auto;
    }
  }
.print-preview-container {
   .print-preview-header {
      padding: 15px;
      border-bottom: 1px solid #e4e7ed;
      text-align: center;
      .el-button {
         margin: 0 10px;
      }
   }
   .print-preview-content {
      padding: 20px;
      background-color: #f5f5f5;
      min-height: 400px;
   }
}
  .print-preview-container {
    .print-preview-header {
      padding: 15px;
      border-bottom: 1px solid #e4e7ed;
      text-align: center;
.print-page {
   width: 220mm;
   height: 90mm;
   padding: 10mm;
   margin: 0 auto;
   background: white;
   box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
   margin-bottom: 10px;
   box-sizing: border-box;
}
      .el-button {
        margin: 0 10px;
      }
    }
.delivery-note {
   width: 100%;
   height: 100%;
   font-family: "SimSun", serif;
   font-size: 10px;
   line-height: 1.2;
   display: flex;
   flex-direction: column;
}
    .print-preview-content {
      padding: 20px;
      background-color: #f5f5f5;
      min-height: 400px;
    }
  }
.header {
   text-align: center;
   margin-bottom: 8px;
   .company-name {
      font-size: 18px;
      font-weight: bold;
      margin-bottom: 4px;
   }
   .document-title {
      font-size: 16px;
      font-weight: bold;
   }
}
  .print-page {
    width: 220mm;
    height: 90mm;
    padding: 10mm;
    margin: 0 auto;
    background: white;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
    margin-bottom: 10px;
    box-sizing: border-box;
  }
.info-section {
   margin-bottom: 8px;
   display: flex;
   justify-content: space-between;
   align-items: center;
   .info-row {
      line-height: 20px;
      .label {
         font-weight: bold;
         width: 60px;
         font-size: 14px;
      }
      .value {
         margin-right: 20px;
         min-width: 80px;
         font-size: 14px;
      }
   }
}
  .delivery-note {
    width: 100%;
    height: 100%;
    font-family: "SimSun", serif;
    font-size: 10px;
    line-height: 1.2;
    display: flex;
    flex-direction: column;
  }
.table-section {
   margin-bottom: 4px;
   flex: 1;
   .product-table {
      width: 100%;
      border-collapse: collapse;
      border: 1px solid #000;
      th, td {
         border: 1px solid #000;
         padding: 6px;
         text-align: center;
         font-size: 14px;
         line-height: 1.4;
      }
      th {
         font-weight: bold;
      }
      .total-label {
         text-align: right;
         font-weight: bold;
      }
      .total-value {
         font-weight: bold;
      }
   }
}
  .header {
    text-align: center;
    margin-bottom: 8px;
.footer-section {
   .footer-row {
      display: flex;
      margin-bottom: 3px;
      line-height: 20px;
      justify-content: space-between;
      .footer-item {
         display: flex;
         margin-right: 20px;
         .label {
            font-weight: bold;
            width: 80px;
            font-size: 14px;
         }
         .value {
            min-width: 80px;
            font-size: 14px;
         }
         &.address-item {
            .address-value {
               min-width: 200px;
            }
         }
      }
   }
}
    .company-name {
      font-size: 18px;
      font-weight: bold;
      margin-bottom: 4px;
    }
@media print {
   .app-container {
      display: none;
   }
   .print-page {
      box-shadow: none;
      margin: 0;
      padding: 10mm;
      padding-left: 20mm;
      page-break-inside: avoid;
      page-break-after: always;
   }
   .print-page:last-child {
      page-break-after: avoid;
   }
}
    .document-title {
      font-size: 16px;
      font-weight: bold;
    }
  }
  .info-section {
    margin-bottom: 8px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    .info-row {
      line-height: 20px;
      .label {
        font-weight: bold;
        width: 60px;
        font-size: 14px;
      }
      .value {
        margin-right: 20px;
        min-width: 80px;
        font-size: 14px;
      }
    }
  }
  .table-section {
    margin-bottom: 4px;
    flex: 1;
    .product-table {
      width: 100%;
      border-collapse: collapse;
      border: 1px solid #000;
      th,
      td {
        border: 1px solid #000;
        padding: 6px;
        text-align: center;
        font-size: 14px;
        line-height: 1.4;
      }
      th {
        font-weight: bold;
      }
      .total-label {
        text-align: right;
        font-weight: bold;
      }
      .total-value {
        font-weight: bold;
      }
    }
  }
  .footer-section {
    .footer-row {
      display: flex;
      margin-bottom: 3px;
      line-height: 20px;
      justify-content: space-between;
      .footer-item {
        display: flex;
        margin-right: 20px;
        .label {
          font-weight: bold;
          width: 80px;
          font-size: 14px;
        }
        .value {
          min-width: 80px;
          font-size: 14px;
        }
        &.address-item {
          .address-value {
            min-width: 200px;
          }
        }
      }
    }
  }
  @media print {
    .app-container {
      display: none;
    }
    .print-page {
      box-shadow: none;
      margin: 0;
      padding: 10mm;
      padding-left: 20mm;
      page-break-inside: avoid;
      page-break-after: always;
    }
    .print-page:last-child {
      page-break-after: avoid;
    }
  }
</style>