src/views/inventoryManagement/dispatchLog/Record.vue
@@ -18,7 +18,7 @@
            </el-form-item>
          </el-col>
          <el-col :span="4">
            <el-form-item label="产品大类"
            <el-form-item label="油品"
                          prop="productName">
              <el-input v-model="searchForm.productName"
                        style="width: 240px"
@@ -102,46 +102,211 @@
                         label="序号"
                         type="index"
                         width="60" />
        <el-table-column label="出库批次"
                         prop="outboundBatches"
                         min-width="100"
                         show-overflow-tooltip />
        <el-table-column label="出库日期"
                         prop="createTime"
                         show-overflow-tooltip />
        <el-table-column label="产品大类"
                         prop="productName"
                         show-overflow-tooltip />
        <el-table-column label="规格型号"
                         prop="model"
                         show-overflow-tooltip />
        <el-table-column label="批号"
                         prop="batchNo"
                         show-overflow-tooltip />
        <el-table-column label="单位"
                         prop="unit"
                         show-overflow-tooltip />
        <el-table-column label="出库数量"
                         prop="stockOutNum"
                         show-overflow-tooltip />
        <el-table-column label="出库人"
                         prop="createBy"
                         show-overflow-tooltip />
        <el-table-column label="来源"
                         prop="recordType"
                         show-overflow-tooltip>
          <template #default="scope">
            {{ getRecordType(scope.row.recordType) }}
          </template>
        <el-table-column label="出库信息"
                         align="center"
                         :header-cell-style="groupHeaderStyle">
          <el-table-column label="出库批次"
                           prop="outboundBatches"
                           min-width="120"
                           show-overflow-tooltip />
          <el-table-column label="出库日期"
                           prop="outDate"
                           min-width="110"
                           show-overflow-tooltip />
          <el-table-column label="出库类别"
                           prop="outCategory"
                           min-width="90"
                           show-overflow-tooltip />
          <el-table-column label="油库"
                           prop="oilDepotName"
                           min-width="160"
                           show-overflow-tooltip />
          <el-table-column label="储罐号"
                           prop="tankNo"
                           min-width="90"
                           show-overflow-tooltip />
          <el-table-column label="油品"
                           prop="productName"
                           min-width="90"
                           show-overflow-tooltip />
          <el-table-column label="出库吨数(吨)"
                           prop="outTonnage"
                           min-width="110"
                           show-overflow-tooltip />
          <el-table-column label="规格型号"
                           prop="model"
                           min-width="110"
                           show-overflow-tooltip />
          <el-table-column label="批号"
                           prop="batchNo"
                           min-width="140"
                           show-overflow-tooltip />
          <el-table-column label="单位"
                           prop="unit"
                           min-width="70"
                           show-overflow-tooltip />
          <el-table-column label="出库数量"
                           prop="stockOutNum"
                           min-width="100"
                           show-overflow-tooltip />
          <el-table-column label="实际扣减数量"
                           prop="deductQuantity"
                           min-width="120"
                           show-overflow-tooltip />
          <el-table-column label="剩余油量(吨)"
                           prop="residualOil"
                           min-width="110"
                           show-overflow-tooltip />
          <el-table-column label="出库人"
                           prop="createBy"
                           min-width="90"
                           show-overflow-tooltip />
          <el-table-column label="发货单号"
                           prop="shippingNo"
                           min-width="140"
                           show-overflow-tooltip />
          <el-table-column label="来源"
                           prop="recordType"
                           min-width="90"
                           show-overflow-tooltip>
            <template #default="scope">
              {{ getRecordType(scope.row.recordType) }}
            </template>
          </el-table-column>
          <el-table-column label="审批状态"
                           prop="approvalStatus"
                           min-width="100"
                           show-overflow-tooltip>
            <template #default="scope">
              <el-tag :type="getApprovalStatusTagType(scope.row.approvalStatus)"
                      size="small">
                {{ getApprovalStatusLabel(scope.row.approvalStatus) }}
              </el-tag>
            </template>
          </el-table-column>
        </el-table-column>
        <el-table-column label="审批状态"
                         prop="approvalStatus"
                         show-overflow-tooltip>
        <el-table-column label="客户信息"
                         align="center"
                         :header-cell-style="groupHeaderStyle">
          <el-table-column label="客户名称"
                           prop="customerName"
                           min-width="160"
                           show-overflow-tooltip />
          <el-table-column label="客户对接人"
                           prop="contactPerson"
                           min-width="100"
                           show-overflow-tooltip />
          <el-table-column label="对接人电话"
                           prop="contactPhone"
                           min-width="120"
                           show-overflow-tooltip />
        </el-table-column>
        <el-table-column label="物流信息"
                         align="center"
                         :header-cell-style="groupHeaderStyle">
          <el-table-column label="司机姓名"
                           prop="driverName"
                           min-width="100"
                           show-overflow-tooltip />
          <el-table-column label="司机电话"
                           prop="driverPhone"
                           min-width="120"
                           show-overflow-tooltip />
          <el-table-column label="押运员姓名"
                           prop="escortName"
                           min-width="100"
                           show-overflow-tooltip />
          <el-table-column label="押运员电话"
                           prop="escortPhone"
                           min-width="120"
                           show-overflow-tooltip />
          <el-table-column label="车牌号"
                           prop="truckPlateNo"
                           min-width="110"
                           show-overflow-tooltip />
          <el-table-column label="车挂牌号"
                           prop="trailerPlateNo"
                           min-width="110"
                           show-overflow-tooltip />
        </el-table-column>
        <el-table-column label="装油操作信息"
                         align="center"
                         :header-cell-style="groupHeaderStyle">
          <el-table-column label="装油检验"
                           prop="loadingInspectionStatus"
                           min-width="90"
                           show-overflow-tooltip />
          <el-table-column label="装车鹤位"
                           prop="loadingCranePosition"
                           min-width="100"
                           show-overflow-tooltip />
          <el-table-column label="密度"
                           prop="density"
                           min-width="80"
                           show-overflow-tooltip />
          <el-table-column label="装油拍照"
                           prop="loadingPhotos"
                           align="center"
                           min-width="90">
            <template #default="scope">
              <el-image v-if="toPhotoArray(scope.row.loadingPhotos).length"
                        :src="getPhotoUrl(toPhotoArray(scope.row.loadingPhotos)[0])"
                        :preview-src-list="getPhotoUrls(scope.row.loadingPhotos)"
                        preview-teleported
                        fit="cover"
                        style="width: 40px; height: 40px; border-radius: 4px" />
              <span v-else>--</span>
            </template>
          </el-table-column>
        </el-table-column>
        <el-table-column label="出库过磅数据"
                         align="center"
                         :header-cell-style="groupHeaderStyle">
          <el-table-column label="毛重(吨)"
                           prop="grossWeight"
                           min-width="90"
                           show-overflow-tooltip />
          <el-table-column label="皮重(吨)"
                           prop="tareWeight"
                           min-width="90"
                           show-overflow-tooltip />
          <el-table-column label="净重(吨)"
                           prop="netWeight"
                           min-width="90"
                           show-overflow-tooltip />
          <el-table-column label="亏量(吨)"
                           prop="lossQuantity"
                           min-width="90"
                           show-overflow-tooltip />
          <el-table-column label="实际出库体积(升)"
                           prop="actualVolume"
                           min-width="130"
                           show-overflow-tooltip />
          <el-table-column label="磅单"
                           prop="poundPhotos"
                           align="center"
                           min-width="90">
            <template #default="scope">
              <el-image v-if="toPhotoArray(scope.row.poundPhotos).length"
                        :src="getPhotoUrl(toPhotoArray(scope.row.poundPhotos)[0])"
                        :preview-src-list="getPhotoUrls(scope.row.poundPhotos)"
                        preview-teleported
                        fit="cover"
                        style="width: 40px; height: 40px; border-radius: 4px" />
              <span v-else>--</span>
            </template>
          </el-table-column>
        </el-table-column>
        <el-table-column fixed="right"
                         label="操作"
                         width="110"
                         align="center">
          <template #default="scope">
            <el-tag :type="getApprovalStatusTagType(scope.row.approvalStatus)"
                    size="small">
              {{ getApprovalStatusLabel(scope.row.approvalStatus) }}
            </el-tag>
            <el-button v-if="isSalesOutRecord(scope.row)"
                       link
                       type="primary"
                       @click="openResidualOil(scope.row)">录入残油
            </el-button>
          </template>
        </el-table-column>
      </el-table>
@@ -152,6 +317,41 @@
                  :limit="page.size"
                  @pagination="paginationChange" />
    </div>
    <!-- 残油录入:送完货后回填剩余油量,只更新 residualOil 一列 -->
    <el-dialog v-model="residualDialogVisible"
               title="录入剩余油量"
               width="30%"
               append-to-body>
      <el-form label-width="130px"
               label-position="top">
        <el-form-item label="出库批次">
          <el-input :model-value="residualForm.outboundBatches || '--'"
                    readonly />
        </el-form-item>
        <el-form-item label="车牌号">
          <el-input :model-value="residualForm.truckPlateNo || '--'"
                    readonly />
        </el-form-item>
        <el-form-item label="出库数量(吨)">
          <el-input :model-value="residualForm.stockOutNum ?? '--'"
                    readonly />
        </el-form-item>
        <el-form-item label="剩余油量(吨)">
          <el-input-number v-model="residualForm.residualOil"
                           :precision="4"
                           :step="1"
                           :min="0"
                           style="width: 100%" />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary"
                     @click="submitResidualOil">确认</el-button>
          <el-button @click="residualDialogVisible = false">取消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
@@ -166,6 +366,7 @@
    delPendingStockOut,
    batchApproveStockOutRecords,
    batchUnapproveStockOutRecords,
    updateResidualOil,
  } from "@/api/inventoryManagement/stockOut.js";
  import {
    findAllQualifiedStockOutRecordTypeOptions,
@@ -290,6 +491,40 @@
    return "warning";
  };
  // 分组父表头样式:区分各分类
  const groupHeaderStyle = {
    background: "#e8f3ff",
    color: "#1d6fd8",
    fontWeight: "700",
    fontSize: "13px",
  };
  // 照片字段后端存的是 JSON 字符串,出参需自行解析
  const toPhotoArray = value => {
    if (!value) {
      return [];
    }
    if (Array.isArray(value)) {
      return value;
    }
    if (typeof value === "string") {
      try {
        const parsed = JSON.parse(value);
        return Array.isArray(parsed) ? parsed : [];
      } catch (e) {
        return [];
      }
    }
    return [];
  };
  const getPhotoUrl = photo =>
    typeof photo === "string" ? photo : photo?.url || photo?.previewURL || "";
  // 图片列:取全部地址用于预览
  const getPhotoUrls = photos =>
    toPhotoArray(photos).map(getPhotoUrl).filter(Boolean);
  // 获取来源类型选项
  const fetchStockRecordTypeOptions = () => {
    if (props.type === "0") {
@@ -349,6 +584,54 @@
  const expandedRowKeys = ref([]);
  // 残油录入:只对销售类出库开放(残油链只对 outCategory='销售' 生效)
  const residualDialogVisible = ref(false);
  const residualForm = ref({
    id: null,
    outboundBatches: "",
    truckPlateNo: "",
    stockOutNum: null,
    residualOil: null,
  });
  const isSalesOutRecord = row => row?.outCategory === "销售";
  const openResidualOil = row => {
    residualForm.value = {
      id: row.id,
      outboundBatches: row.outboundBatches || "",
      truckPlateNo: row.truckPlateNo || "",
      stockOutNum: row.stockOutNum ?? null,
      residualOil: row.residualOil ?? null,
    };
    residualDialogVisible.value = true;
  };
  const submitResidualOil = () => {
    const { id, residualOil, stockOutNum } = residualForm.value;
    if (residualOil === null || residualOil === undefined || residualOil === "") {
      proxy.$modal.msgWarning("请输入剩余油量");
      return;
    }
    if (Number(residualOil) < 0) {
      proxy.$modal.msgWarning("剩余油量不能小于0");
      return;
    }
    if (
      stockOutNum !== null &&
      stockOutNum !== undefined &&
      Number(residualOil) > Number(stockOutNum)
    ) {
      proxy.$modal.msgWarning("剩余油量不能大于出库数量");
      return;
    }
    updateResidualOil(id, { residualOil }).then(() => {
      proxy.$modal.msgSuccess("录入成功");
      residualDialogVisible.value = false;
      getList();
    });
  };
  const handleBatchApprove = () => {
    if (selectedRows.value.length === 0) {
      proxy.$modal.msgWarning("请选择数据");