新增/编辑台账。新增台账的表单换成跳转到页面新增,否则表单太小查看很不方便。新增完成之后再回到台账页面。需要汇总出数量、结算单片面积、面积。
已修改2个文件
908 ■■■■■ 文件已修改
src/components/Dialog/FormDialog.vue 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/salesLedger/index.vue 902 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Dialog/FormDialog.vue
@@ -14,7 +14,7 @@
                     @click="handleConfirm">
            确认
          </el-button>
          <el-button :disabled="loading" @click="handleCancel">取消</el-button>
          <el-button :disabled="loading" @click="handleCancel">{{ cancelButtonText }}</el-button>
        </slot>
      </div>
    </template>
@@ -56,6 +56,9 @@
  // 详情模式不展示“确认”按钮,其它类型正常显示
  const showConfirm = computed(() => props.operationType !== "detail");
  const cancelButtonText = computed(() =>
    props.operationType === "detail" ? "关闭" : "取消"
  );
  const computedTitle = computed(() => {
    if (typeof props.title === "function") {
@@ -83,4 +86,3 @@
    text-align: center;
  }
</style>
src/views/salesManagement/salesLedger/index.vue
@@ -1,5 +1,712 @@
<template>
  <div class="app-container">
    <template v-if="isFormPageMode">
      <div class="sales-ledger-page-header">
        <div>
          <el-button class="sales-ledger-page-back"
                     @click="exitFormPage()">返回台账</el-button>
          <div class="sales-ledger-page-title">{{ pageFormTitle }}</div>
          <div class="sales-ledger-page-subtitle">{{ pageFormSubtitle }}</div>
        </div>
      </div>
      <div class="sales-ledger-page-form">
        <el-form :model="form"
                 label-width="140px"
                 label-position="top"
                 :rules="rules"
                 @keydown.capture="handleTabScrollFollow"
                 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>
            </el-col>
            <el-col :span="12">
              <el-form-item label="业务员:"
                            prop="salesman">
                <el-select v-model="form.salesman"
                           placeholder="请选择"
                           clearable
                           :disabled="isReviewedEdit">
                  <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"
                           filterable
                           placeholder="请选择"
                           clearable
                           :disabled="isReviewedEdit">
                  <el-option v-for="item in customerOption"
                             :key="item.id"
                             :label="item.customerName"
                             :value="item.id">
                    {{ item.customerName + (item.taxpayerIdentificationNumber ? "——" + 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="isReviewedEdit" />
              </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="isReviewedEdit" />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="交货日期:"
                            prop="deliveryDate">
                <el-date-picker style="width: 100%"
                                v-model="form.deliveryDate"
                                value-format="YYYY-MM-DD"
                                format="YYYY-MM-DD"
                                type="date"
                                placeholder="请选择"
                                clearable
                                :disabled="isReviewedEdit" />
              </el-form-item>
            </el-col>
          </el-row>
          <el-row :gutter="30">
            <el-col :span="12">
              <el-form-item label="录入人:"
                            prop="entryPerson">
                <el-select v-model="form.entryPerson"
                           filterable
                           default-first-option
                           :reserve-keyword="false"
                           placeholder="请选择"
                           clearable
                           @change="changs"
                           :disabled="isReviewedEdit">
                  <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
                                :disabled="isReviewedEdit" />
              </el-form-item>
            </el-col>
          </el-row>
          <el-row>
            <el-form-item label="产品信息:"
                          prop="entryDate">
              <el-button type="primary"
                         :disabled="hasEditingProductRow() || isReviewedEdit"
                         @click="addProductInline">
                添加
              </el-button>
              <el-button plain
                         type="danger"
                         :disabled="isReviewedEdit"
                         @click="deleteProduct">删除</el-button>
            </el-form-item>
          </el-row>
          <el-table :data="productData"
                    border
                    @selection-change="productSelected"
                    show-summary
                    :summary-method="summarizeProductTable">
            <el-table-column align="center"
                             type="selection"
                             width="55"
                             :selectable="(row) => !isProductShipped(row)" />
            <el-table-column align="center"
                             label="序号"
                             type="index"
                             width="60" />
            <el-table-column label="产品大类"
                             prop="productCategory"
                             min-width="160">
              <template #default="scope">
                <el-tree-select v-if="scope.row.__editing"
                                v-model="scope.row.__productCategoryId"
                                placeholder="请选择"
                                clearable
                                filterable
                                check-strictly
                                :data="productOptions"
                                :render-after-expand="false"
                                style="width: 100%"
                                :filter-node-method="filterProductCategoryNode"
                                @change="(val) => handleInlineProductCategoryChange(scope.row, val)"
                                :disabled="isReviewedEdit" />
                <span v-else>{{ scope.row.productCategory ?? "" }}</span>
              </template>
            </el-table-column>
            <el-table-column label="规格型号"
                             prop="specificationModel"
                             min-width="200">
              <template #default="scope">
                <el-select v-if="scope.row.__editing"
                           v-model="scope.row.productModelId"
                           placeholder="请选择"
                           clearable
                           filterable
                           style="width: 100%"
                           @change="(val) => handleInlineProductModelChange(scope.row, val)"
                           :disabled="isReviewedEdit">
                  <el-option v-for="item in modelOptions"
                             :key="item.id"
                             :label="item.model"
                             :value="item.id" />
                </el-select>
                <span v-else>{{ scope.row.specificationModel ?? "" }}</span>
              </template>
            </el-table-column>
            <el-table-column label="厚度(mm)"
                             prop="thickness"
                             min-width="160">
              <template #default="scope">
                <el-input-number v-if="scope.row.__editing"
                                 controls-position="right"
                                 v-model="scope.row.thickness"
                                 :min="0"
                                 :step="1"
                                 :precision="2"
                                 style="width: 100%"
                                 placeholder="请输入"
                                 clearable
                                 :disabled="isReviewedEdit" />
                <span v-else>{{ scope.row.thickness ?? "" }}</span>
              </template>
            </el-table-column>
            <el-table-column label="楼层编号"
                             prop="floorCode"
                             min-width="250"
                             show-overflow-tooltip>
              <template #default="scope">
                <el-input v-if="scope.row.__editing"
                          v-model="scope.row.floorCode"
                          placeholder="请输入"
                          clearable
                          style="width: 100%"
                          :disabled="isReviewedEdit" />
                <span v-else>{{ scope.row.floorCode ?? "" }}</span>
              </template>
            </el-table-column>
            <el-table-column label="含税单价(元)"
                             prop="taxInclusiveUnitPrice"
                             min-width="160">
              <template #default="scope">
                <el-input-number v-if="scope.row.__editing"
                                 :step="0.01"
                                 :min="0"
                                 :precision="2"
                                 style="width: 100%"
                                 v-model="scope.row.taxInclusiveUnitPrice"
                                 placeholder="请输入"
                                 clearable
                                 @change="() => handleInlineUnitPriceChange(scope.row)"
                                 @input="() => handleInlineUnitPriceChange(scope.row)" />
                <span v-else>{{ formattedNumber(null, null, scope.row.taxInclusiveUnitPrice) }}</span>
              </template>
            </el-table-column>
            <el-table-column label="宽(mm)"
                             prop="width"
                             min-width="160">
              <template #default="scope">
                <el-input-number v-if="scope.row.__editing"
                                 controls-position="right"
                                 v-model="scope.row.width"
                                 :min="0"
                                 :step="1"
                                 :precision="2"
                                 style="width:100%"
                                 placeholder="请输入"
                                 clearable
                                 @change="() => handleInlineSizeChange(scope.row)"
                                 @input="() => handleInlineSizeChange(scope.row)"
                                 :disabled="isReviewedEdit" />
                <span v-else>{{ scope.row.width ?? "" }}</span>
              </template>
            </el-table-column>
            <el-table-column label="高(mm)"
                             prop="height"
                             min-width="160">
              <template #default="scope">
                <el-input-number v-if="scope.row.__editing"
                                 controls-position="right"
                                 v-model="scope.row.height"
                                 :min="0"
                                 :step="1"
                                 :precision="2"
                                 style="width: 100%"
                                 placeholder="请输入"
                                 clearable
                                 @change="() => handleInlineSizeChange(scope.row)"
                                 @input="() => handleInlineSizeChange(scope.row)"
                                 :disabled="isReviewedEdit" />
                <span v-else>{{ scope.row.height ?? "" }}</span>
              </template>
            </el-table-column>
            <el-table-column label="数量"
                             prop="quantity"
                             min-width="150">
              <template #default="scope">
                <el-input-number v-if="scope.row.__editing"
                                 controls-position="right"
                                 v-model="scope.row.quantity"
                                 :step="1"
                                 :min="0"
                                 :precision="0"
                                 style="width: 100%"
                                 placeholder="请输入"
                                 clearable
                                 @change="() => handleInlineQuantityChange(scope.row)"
                                 @input="() => handleInlineQuantityChange(scope.row)"
                                 :disabled="isReviewedEdit" />
                <span v-else>{{ scope.row.quantity ?? "" }}</span>
              </template>
            </el-table-column>
            <el-table-column label="结算单片面积(㎡)"
                             prop="settlePieceArea"
                             min-width="200">
              <template #default="scope">
                <el-input-number v-if="scope.row.__editing"
                                 controls-position="right"
                                 v-model="scope.row.settlePieceArea"
                                 :min="0"
                                 :step="1"
                                 :precision="4"
                                 style="width: 100%"
                                 placeholder="请输入"
                                 clearable
                                 @change="() => handleInlineSettleAreaChange(scope.row)"
                                 :disabled="isReviewedEdit" />
                <span v-else>{{ scope.row.settlePieceArea ? Number(scope.row.settlePieceArea).toFixed(4) : "" }}</span>
              </template>
            </el-table-column>
            <el-table-column label="面积(m²)"
                             prop="actualTotalArea"
                             min-width="200">
              <template #default="scope">
                <el-input-number v-if="scope.row.__editing"
                                 controls-position="right"
                                 v-model="scope.row.actualTotalArea"
                                 :min="0"
                                 :step="1"
                                 :precision="4"
                                 style="width: 100%"
                                 placeholder="自动计算"
                                 :disabled="isReviewedEdit" />
                <span v-else>{{ scope.row.actualTotalArea ? Number(scope.row.actualTotalArea).toFixed(4) : "" }}</span>
              </template>
            </el-table-column>
            <el-table-column label="税率(%)"
                             prop="taxRate"
                             min-width="120">
              <template #default="scope">
                <el-select v-if="scope.row.__editing"
                           v-model="scope.row.taxRate"
                           placeholder="请选择"
                           clearable
                           style="width: 100%"
                           @change="() => handleInlineTaxRateChange(scope.row)"
                           :disabled="isReviewedEdit">
                  <el-option label="1"
                             value="1" />
                  <el-option label="3"
                             value="3" />
                  <el-option label="6"
                             value="6" />
                  <el-option label="9"
                             value="9" />
                  <el-option label="13"
                             value="13" />
                </el-select>
                <span v-else>{{ scope.row.taxRate ?? "" }}</span>
              </template>
            </el-table-column>
            <el-table-column label="含税总价(元)"
                             prop="taxInclusiveTotalPrice"
                             :formatter="formattedNumber"
                             min-width="120" />
            <el-table-column label="不含税总价(元)"
                             prop="taxExclusiveTotalPrice"
                             :formatter="formattedNumber"
                             min-width="120" />
            <el-table-column label="加工要求"
                             prop="processRequirement"
                             min-width="160"
                             show-overflow-tooltip>
              <template #default="scope">
                <el-input v-if="scope.row.__editing"
                          v-model="scope.row.processRequirement"
                          placeholder="请输入"
                          clearable
                          style="width: 100%"
                          :disabled="isReviewedEdit" />
                <span v-else>{{ scope.row.processRequirement ?? "" }}</span>
              </template>
            </el-table-column>
            <el-table-column label="发票类型"
                             prop="invoiceType"
                             min-width="120">
              <template #default="scope">
                <el-select v-if="scope.row.__editing"
                           v-model="scope.row.invoiceType"
                           placeholder="请选择"
                           clearable
                           style="width: 100%"
                           :disabled="isReviewedEdit">
                  <el-option label="增普票"
                             value="增普票" />
                  <el-option label="增专票"
                             value="增专票" />
                </el-select>
                <span v-else>{{ scope.row.invoiceType ?? "" }}</span>
              </template>
            </el-table-column>
            <el-table-column label="备注"
                             prop="remark"
                             min-width="140"
                             show-overflow-tooltip>
              <template #default="scope">
                <el-input v-if="scope.row.__editing"
                          v-model="scope.row.remark"
                          placeholder="请输入"
                          clearable
                          style="width: 100%"
                          :disabled="isReviewedEdit" />
                <span v-else>{{ scope.row.remark ?? "" }}</span>
              </template>
            </el-table-column>
            <el-table-column label="重箱"
                             prop="heavyBox"
                             min-width="100">
              <template #default="scope">
                <el-input v-if="scope.row.__editing"
                          v-model="scope.row.heavyBox"
                          placeholder="请输入"
                          clearable
                          style="width: 100%"
                          :disabled="isReviewedEdit" />
                <span v-else>{{ scope.row.heavyBox ?? "" }}</span>
              </template>
            </el-table-column>
            <el-table-column fixed="right"
                             label="操作"
                             min-width="220"
                             align="center">
              <template #default="scope">
                <template v-if="scope.row.__editing">
                  <el-button link
                             type="primary"
                             size="small"
                             @click="saveProductInline(scope.row, scope.$index)">保存</el-button>
                  <el-button link
                             type="danger"
                             size="small"
                             @click="cancelProductInline(scope.row, scope.$index)">取消</el-button>
                  <el-popover :width="560"
                              trigger="click"
                              :hide-after="0"
                              :visible="scope.row.__otherAmountPopoverVisible"
                              @update:visible="(val) => handleOtherAmountPopoverVisibleChange(scope.row, val)">
                    <template #reference>
                      <el-button link
                                 type="primary"
                                 size="small"
                                 @click="openOtherAmountInline(scope.row)">
                        额外加工({{ (scope.row.salesProductProcessList || []).length || 0 }})
                      </el-button>
                    </template>
                    <div style="display:flex; align-items:center; justify-content:space-between; gap: 10px; margin-bottom: 8px;">
                      <div style="font-weight: 600; color:#303133;">
                        额外加工
                      </div>
                      <el-button type="primary"
                                 plain
                                 size="small"
                                 :disabled="isReviewedEdit"
                                 @click="startAddOtherAmountForRow(scope.row)">
                        新增
                      </el-button>
                    </div>
                    <div v-if="scope.row.__inlineOtherAmountAdding"
                         style="display:flex; flex-direction:column; gap: 8px; margin-bottom: 10px;"
                         @click.stop>
                      <el-select v-model="scope.row.__inlineOtherAmountAddId"
                                 filterable
                                 clearable
                                 placeholder="请选择额外加工项目"
                                 style="width: 100%;">
                        <el-option v-for="item in otherAmountSelectOptions"
                                   :key="item.id"
                                   :label="item.processName"
                                   :value="item.id" />
                      </el-select>
                      <div style="display:flex; justify-content:flex-end; gap: 8px;">
                        <el-button size="small"
                                   @click="scope.row.__inlineOtherAmountAdding = false; scope.row.__inlineOtherAmountAddId = null">
                          取消
                        </el-button>
                        <el-button type="primary"
                                   size="small"
                                   :disabled="isReviewedEdit || scope.row.__inlineOtherAmountAddId === null || scope.row.__inlineOtherAmountAddId === undefined || scope.row.__inlineOtherAmountAddId === ''"
                                   @click="confirmAddOtherAmountForRow(scope.row)">
                          确认添加
                        </el-button>
                      </div>
                    </div>
                    <div v-if="Array.isArray(scope.row.salesProductProcessList) && scope.row.salesProductProcessList.length > 0"
                         style="display:flex; flex-wrap:wrap; gap: 8px;">
                      <div v-for="(item, idx) in scope.row.salesProductProcessList"
                           :key="String(item.id) + '_' + idx"
                           style="display:flex; align-items:center; gap: 8px; flex: 0 0 calc(50% - 4px); max-width: calc(50% - 4px);">
                        <el-tag type="info"
                                style="max-width: 170px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;">
                          {{ item.processName }}
                        </el-tag>
                        <el-input-number v-model="item.quantity"
                                         :min="0"
                                         :step="1"
                                         :precision="0"
                                         style="width: 120px;"
                                         placeholder="数量"
                                         :disabled="isReviewedEdit"
                                         @change="handleOtherAmountQuantityChange(scope.row)" />
                        <el-button type="danger"
                                   link
                                   size="small"
                                   :disabled="isReviewedEdit"
                                   @click="removeOtherAmountAtForRow(scope.row, idx)">
                          删除
                        </el-button>
                      </div>
                    </div>
                    <div v-else
                         style="color:#909399; font-size: 13px;">
                      暂无额外加工
                    </div>
                  </el-popover>
                </template>
                <template v-else>
                  <el-button v-if="isReviewedEdit"
                             link
                             type="primary"
                             size="small"
                             :disabled="isProductShipped(scope.row)"
                             @click="editPriceOnly(scope.row)">
                    修改单价
                  </el-button>
                  <template v-if="!isReviewedEdit">
                    <el-button link
                               type="primary"
                               size="small"
                               :disabled="isProductShipped(scope.row)"
                               @click="editProductInline(scope.row, scope.$index)">
                      编辑
                    </el-button>
                    <el-button link
                               type="primary"
                               size="small"
                               :disabled="isProductShipped(scope.row)"
                               @click="copyProductInline(scope.row, scope.$index)">
                      复制新建
                    </el-button>
                  </template>
                  <el-popover :width="560"
                              trigger="click"
                              :hide-after="0"
                              :visible="scope.row.__otherAmountPopoverVisible"
                              @update:visible="(val) => handleOtherAmountPopoverVisibleChange(scope.row, val)">
                    <template #reference>
                      <el-button link
                                 type="primary"
                                 size="small"
                                 :disabled="isProductShipped(scope.row)"
                                 @click="openOtherAmountInline(scope.row)">
                        额外加工({{ (scope.row.salesProductProcessList || []).length || 0 }})
                      </el-button>
                    </template>
                    <div style="display:flex; align-items:center; justify-content:space-between; gap: 10px; margin-bottom: 8px;">
                      <div style="font-weight: 600; color:#303133;">
                        额外加工
                      </div>
                      <el-button type="primary"
                                 plain
                                 size="small"
                                 :disabled="isProductShipped(scope.row) || isReviewedEdit"
                                 @click="startAddOtherAmountForRow(scope.row)">
                        新增
                      </el-button>
                    </div>
                    <div v-if="scope.row.__inlineOtherAmountAdding"
                         style="display:flex; flex-direction:column; gap: 8px; margin-bottom: 10px;"
                         @click.stop>
                      <el-select v-model="scope.row.__inlineOtherAmountAddId"
                                 filterable
                                 clearable
                                 placeholder="请选择额外加工项目"
                                 style="width: 100%;"
                                 :disabled="isProductShipped(scope.row) || isReviewedEdit">
                        <el-option v-for="item in otherAmountSelectOptions"
                                   :key="item.id"
                                   :label="item.processName"
                                   :value="item.id" />
                      </el-select>
                      <div style="display:flex; justify-content:flex-end; gap: 8px;">
                        <el-button size="small"
                                   :disabled="isProductShipped(scope.row) || isReviewedEdit"
                                   @click="scope.row.__inlineOtherAmountAdding = false; scope.row.__inlineOtherAmountAddId = null">
                          取消
                        </el-button>
                        <el-button type="primary"
                                   size="small"
                                   :disabled="isProductShipped(scope.row) || isReviewedEdit || scope.row.__inlineOtherAmountAddId === null || scope.row.__inlineOtherAmountAddId === undefined || scope.row.__inlineOtherAmountAddId === ''"
                                   @click="confirmAddOtherAmountForRow(scope.row)">
                          确认添加
                        </el-button>
                      </div>
                    </div>
                    <div v-if="Array.isArray(scope.row.salesProductProcessList) && scope.row.salesProductProcessList.length > 0"
                         style="display:flex; flex-wrap:wrap; gap: 8px;">
                      <div v-for="(item, idx) in scope.row.salesProductProcessList"
                           :key="String(item.id) + '_' + idx"
                           style="display:flex; align-items:center; gap: 8px; flex: 0 0 calc(50% - 4px); max-width: calc(50% - 4px);">
                        <el-tag type="info"
                                style="max-width: 170px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;">
                          {{ item.processName }}
                        </el-tag>
                        <el-input-number v-model="item.quantity"
                                         :min="0"
                                         :step="1"
                                         :precision="0"
                                         style="width: 120px;"
                                         placeholder="数量"
                                         :disabled="isProductShipped(scope.row) || isReviewedEdit"
                                         @change="handleOtherAmountQuantityChange(scope.row)" />
                        <el-button type="danger"
                                   link
                                   size="small"
                                   :disabled="isProductShipped(scope.row) || isReviewedEdit"
                                   @click="removeOtherAmountAtForRow(scope.row, idx)">
                          删除
                        </el-button>
                      </div>
                    </div>
                    <div v-else
                         style="color:#909399; font-size: 13px;">
                      暂无额外加工
                    </div>
                  </el-popover>
                </template>
              </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="isReviewedEdit" />
              </el-form-item>
            </el-col>
          </el-row>
          <el-row :gutter="30">
            <el-col :span="24">
              <el-form-item label="客户备注:"
                            prop="customerRemarks">
                <el-input v-model="form.customerRemarks"
                          placeholder="请输入"
                          clearable
                          type="textarea"
                          :rows="2"
                          :disabled="isReviewedEdit" />
              </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">上传</el-button>
                  <template #tip>
                    <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>
          <div class="sales-ledger-page-actions">
            <el-button type="primary" @click="submitForm">提交</el-button>
          </div>
        </el-form>
      </div>
    </template>
    <template v-else>
    <div class="search_form">
      <el-form :model="searchForm"
               :inline="true">
@@ -348,10 +1055,12 @@
                  :limit="page.size"
                  @pagination="paginationChange" />
    </div>
    <FormDialog v-model="dialogFormVisible"
    </template>
    <FormDialog v-if="!isFormPageMode"
                v-model="dialogFormVisible"
                :title="isCompletedOrder ? '查看销售台账页面(已完成)' : operationType === 'add' ? '新增销售台账页面' : operationType === 'view' ? '查看销售台账页面' : '编辑销售台账页面'"
                :width="'70%'"
                :operation-type="isCompletedOrder ? 'detail' : operationType"
                :operation-type="isCompletedOrder || operationType === 'view' ? 'detail' : operationType"
                @close="closeDia"
                @confirm="submitForm"
                @cancel="closeDia">
@@ -507,7 +1216,7 @@
                  border
                  @selection-change="productSelected"
                  show-summary
                  :summary-method="summarizeMainTable">
                  :summary-method="summarizeProductTable">
          <el-table-column align="center"
                           type="selection"
                           width="55"
@@ -1769,7 +2478,7 @@
<script setup>
  import { getToken } from "@/utils/auth";
  import pagination from "@/components/PIMTable/Pagination.vue";
  import { onMounted, ref, reactive, getCurrentInstance, watch, nextTick } from "vue";
  import { onMounted, ref, reactive, getCurrentInstance, watch, nextTick, computed } from "vue";
  import { addShippingInfo } from "@/api/salesManagement/deliveryLedger.js";
  import { ElMessageBox, ElMessage } from "element-plus";
  import { ArrowDown, WarningFilled } from "@element-plus/icons-vue";
@@ -1814,10 +2523,13 @@
  import { printSalesDeliveryNote } from "./components/salesDeliveryPrint.js";
  import { printSalesLabel } from "./components/salesLabelPrint.js";
  import QRCode from "qrcode";
  import { useRoute, useRouter } from "vue-router";
  // import { salesLedgerProductSetProcessFlowConfig } from "@/api/salesManagement/salesProcessFlowConfig.js";
  const userStore = useUserStore();
  const { proxy } = getCurrentInstance();
  const route = useRoute();
  const router = useRouter();
  const tableData = ref([]);
  const productData = ref([]);
  const selectedRows = ref([]);
@@ -1861,6 +2573,19 @@
  const ledgerQrDialogVisible = ref(false);
  const ledgerQrCompositeUrl = ref("");
  const ledgerQrDownloadBaseName = ref("");
  const pendingAddPrefillDetail = ref(null);
  const pageMode = computed(() => String(route.query.mode || ""));
  const isFormPageMode = computed(() =>
    pageMode.value === "add" || pageMode.value === "edit"
  );
  const pageFormTitle = computed(() =>
    pageMode.value === "edit" ? "编辑销售台账" : "新增销售台账"
  );
  const pageFormSubtitle = computed(() =>
    pageMode.value === "edit"
      ? "编辑完成后将自动返回销售台账列表"
      : "新增完成后将自动返回销售台账列表"
  );
  const sanitizeLedgerQrFilename = s =>
    String(s)
@@ -3074,7 +3799,7 @@
        if (res.newLedgerIds.length === 1) {
          const newId = res.newLedgerIds[0];
          getSalesLedgerWithProducts({ id: newId, type: 1 }).then(detail => {
            openFormWithPreFill(detail);
            enterAddPage(detail);
          });
        }
      }
@@ -3113,11 +3838,12 @@
  };
  /** 用预填数据打开新增台账页面(重新生成场景) */
  const openFormWithPreFill = async (detail) => {
  const openFormWithPreFill = async (detail, keepPageMode = false) => {
    operationType.value = "add";
    form.value = {};
    productData.value = [];
    selectedQuotation.value = null;
    fileList.value = [];
    let userLists = await userListNoPage();
    userList.value = userLists.data;
    customerList().then(res => {
@@ -3138,7 +3864,7 @@
    form.value.customerRemarks = detail.customerRemarks ?? detail.customer_remarks ?? "";
    productData.value = detail.productData || [];
    form.value.deliveryDate = dayjs(form.value.entryDate).add(7, "day").format("YYYY-MM-DD");
    dialogFormVisible.value = true;
    dialogFormVisible.value = !keepPageMode;
  };
  const paginationChange = obj => {
@@ -3614,8 +4340,116 @@
      "taxExclusiveTotalPrice",
    ]);
  };
  const summarizeProductTable = param => {
    return proxy.summarizeTable(param, [
      "quantity",
      "settlePieceArea",
      "actualTotalArea",
      "taxInclusiveTotalPrice",
      "taxExclusiveTotalPrice",
    ]);
  };
  const initAddFormState = async () => {
    operationType.value = "add";
    isCompletedOrder.value = false;
    isReviewedEdit.value = false;
    form.value = {};
    productData.value = [];
    fileList.value = [];
    selectedQuotation.value = null;
    const userLists = await userListNoPage();
    userList.value = userLists.data;
    customerList().then(res => {
      customerOption.value = res;
    });
    form.value.entryPerson = userStore.id;
    form.value.entryDate = getCurrentDate();
    form.value.executionDate = getCurrentDate();
    form.value.customerRemarks = "";
    form.value.deliveryDate = dayjs(form.value.entryDate)
      .add(7, "day")
      .format("YYYY-MM-DD");
  };
  const initEditFormState = async rowId => {
    operationType.value = "edit";
    isCompletedOrder.value = false;
    form.value = {};
    productData.value = [];
    fileList.value = [];
    selectedQuotation.value = null;
    const userLists = await userListNoPage();
    userList.value = userLists.data;
    customerList().then(res => {
      customerOption.value = res;
    });
    currentId.value = rowId;
    const res = await getSalesLedgerWithProducts({ id: rowId, type: 1 });
    form.value = { ...res };
    form.value.entryPerson = Number(res.entryPerson);
    form.value.customerRemarks =
      res?.customerRemarks ?? res?.customer_remarks ?? "";
    productData.value = form.value.productData || [];
    fileList.value = form.value.salesLedgerFiles || [];
    isReviewedEdit.value = Number(res?.reviewStatus) === 1;
  };
  const enterAddPage = async detail => {
    pendingAddPrefillDetail.value = detail || null;
    const query = { ...route.query, mode: "add" };
    await router.push({ path: route.path, query });
  };
  const enterEditPage = async row => {
    const query = { ...route.query, mode: "edit", id: row?.id };
    await router.push({ path: route.path, query });
  };
  const exitFormPage = async (shouldRefresh = false) => {
    const query = { ...route.query };
    delete query.mode;
    delete query.id;
    pendingAddPrefillDetail.value = null;
    await router.push({ path: route.path, query });
    closeDia(false);
    if (shouldRefresh) {
      getList();
    }
  };
  watch(
    pageMode,
    async enabled => {
      if (enabled === "add") {
        await initAddFormState();
        if (pendingAddPrefillDetail.value) {
          await openFormWithPreFill(pendingAddPrefillDetail.value, true);
          pendingAddPrefillDetail.value = null;
        }
        return;
      }
      if (enabled === "edit" && route.query.id) {
        await initEditFormState(route.query.id);
      }
    },
    { immediate: true }
  );
  // 打开弹框
  const openForm = async (type, row) => {
    if (type === "add") {
      await enterAddPage();
      return;
    }
    if (type === "edit") {
      await enterEditPage(row);
      return;
    }
    // 已完成订单强制为只读模式,但附件上传仍可用
    const isCompleted = Number(row?.orderStatus) === 1;
    const effectiveType = isCompleted ? 'view' : type;
@@ -3868,6 +4702,10 @@
        delete submitPayload.paymentMethod;
        addOrUpdateSalesLedger(submitPayload).then(res => {
          proxy.$modal.msgSuccess("提交成功");
          if (isFormPageMode.value) {
            exitFormPage(true);
            return;
          }
          closeDia();
          getList();
        });
@@ -3875,11 +4713,16 @@
    });
  };
  // 关闭弹框
  const closeDia = () => {
  const closeDia = (resetFormRef = true) => {
    if (resetFormRef) {
    proxy.resetForm("formRef");
    }
    dialogFormVisible.value = false;
    isCompletedOrder.value = false;
    isReviewedEdit.value = false;
    if (!isFormPageMode.value) {
      fileList.value = [];
    }
  };
  const productIndex = ref(0);
@@ -5180,6 +6023,44 @@
    margin-bottom: 10px;
  }
  .sales-ledger-page-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 16px;
    margin-bottom: 16px;
  }
  .sales-ledger-page-title {
    font-size: 22px;
    font-weight: 600;
    color: #303133;
    line-height: 1.3;
  }
  .sales-ledger-page-back {
    margin-bottom: 12px;
  }
  .sales-ledger-page-subtitle {
    margin-top: 6px;
    font-size: 13px;
    color: #909399;
  }
  .sales-ledger-page-form {
    padding: 20px;
    background: #fff;
    border-radius: 8px;
  }
  .sales-ledger-page-actions {
    display: flex;
    justify-content: center;
    gap: 16px;
    margin-top: 24px;
  }
  .ledger-qr-dialog {
    text-align: center;
    padding-bottom: 8px;
@@ -5241,6 +6122,11 @@
  }
  @media (max-width: 768px) {
    .sales-ledger-page-header {
      flex-direction: column;
      align-items: stretch;
    }
    .approver-node-item {
      flex: 0 0 100%;
    }