spring
2025-11-19 1187936c713bae2ad43063900c7bee80502e091d
src/pages/production/wire/report/wire.vue
@@ -1,41 +1,181 @@
<template>
  <view class="list">
    <z-paging ref="pagingRef" v-model="wireReportList" :fixed="false" @query="getWireReportList">
      <template #top>
        <CardTitle title="报工信息" :hideAction="true" :full="false" @action="addReport" />
    <CardTitle title="报工信息" :hideAction="false" :full="false">
      <template #action>
        <wd-button
          icon="file-add"
          :round="false"
          size="small"
          custom-class="add_btn"
          @click="handleAddParent"
        >
          新增杆包
        </wd-button>
      </template>
      <wd-card
        v-for="(item, index) in wireReportList"
        :key="index"
        type="rectangle"
        custom-class="round"
      >
    </CardTitle>
    <!-- 父级列表(杆包) -->
    <view class="parent-list">
      <wd-card v-for="(item, index) in parentDataList" :key="item.id || index" class="card_bg">
        <template #title>
          <view class="flex justify-between">
            <view>
              <wd-icon name="user" color="#0D867F"></wd-icon>
              <text class="text-[#0D867F] ml-2 font-medium">生产人</text>
              <text class="text-[#333333] ml-2">{{ item.productUser }}</text>
          <view class="flex justify-between w-full">
            <view class="flex items-center">
              <text class="font-medium text-[#252525]">杆包信息</text>
              <view v-if="item.isAutoAdd == 1" class="text-xs text-blue-500 ml-2">自动添加</view>
            </view>
            <!-- <view class="text-[#A8A8A8]" @click="toEdit">编辑</view> -->
            <wd-button plain type="error" size="small" @click="handleDeleteRodBag(item)">
              删除
            </wd-button>
          </view>
        </template>
        <ProductionCard :data="cardAttr" :value="item" />
        <view>
          <wd-row class="my-2" v-if="item.poleNumber">
            <wd-col :span="24">
              <view class="flex">
                <view class="icon_box">
                  <wd-icon name="folder" color="#0D867F"></wd-icon>
                </view>
                <text class="text-[#646874] mx-2">
                  领用杆号:
                  <text class="text-[#252525]">{{ item.poleNumber }}</text>
                </text>
              </view>
            </wd-col>
          </wd-row>
          <wd-row class="my-2" v-if="item.poleModel">
            <wd-col :span="12">
              <view class="flex">
                <view class="icon_box">
                  <wd-icon name="folder" color="#0D867F"></wd-icon>
                </view>
                <text class="text-[#646874] mx-2">
                  杆型号:
                  <text class="text-[#252525]">{{ item.poleModel }}</text>
                </text>
              </view>
            </wd-col>
            <wd-col :span="12">
              <view class="flex">
                <view class="icon_box">
                  <wd-icon name="folder" color="#0D867F"></wd-icon>
                </view>
                <text class="text-[#646874] mx-2">
                  杆包号:
                  <text class="text-[#252525]">{{ item.polePackageNumber }}</text>
                </text>
              </view>
            </wd-col>
          </wd-row>
          <wd-row class="my-2">
            <wd-col :span="24" v-if="item.poleWeight">
              <view class="flex">
                <view class="icon_box">
                  <wd-icon name="folder" color="#0D867F"></wd-icon>
                </view>
                <text class="text-[#646874] mx-2">
                  杆重(kg):
                  <text class="text-[#252525]">{{ item.poleWeight }}</text>
                </text>
              </view>
            </wd-col>
          </wd-row>
          <wd-row class="my-2">
            <wd-col :span="24" v-if="item.supplier">
              <view class="flex">
                <view class="icon_box">
                  <wd-icon name="folder" color="#0D867F"></wd-icon>
                </view>
                <text class="text-[#646874] mx-2">
                  供应商:
                  <text class="text-[#252525]">{{ item.supplier }}</text>
                </text>
              </view>
            </wd-col>
          </wd-row>
          <wd-row class="my-2" v-if="item.isConsumed !== undefined">
            <wd-col :span="24">
              <view class="flex items-center">
                <view class="icon_box">
                  <wd-icon name="folder" color="#0D867F"></wd-icon>
                </view>
                <text class="text-[#646874] mx-2">消耗情况:</text>
                <wd-switch
                  v-model="item.isConsumed"
                  :disabled="false"
                  active-text="已耗完"
                  inactive-text="还剩余"
                  :active-value="1"
                  :inactive-value="0"
                  size="20"
                  @change="handleConsumedChange(item, $event)"
                />
              </view>
            </wd-col>
          </wd-row>
        </view>
        <template #footer>
          <wd-button size="small" plain style="margin-right: 10px" @click="toAttachment(item)">
            附件
          </wd-button>
          <wd-button size="small" plain @click="toCheck(item.id)">自检</wd-button>
          <view class="flex justify-start">
            <wd-button plain size="small" type="primary" @click="openChildDialog(item)">
              报工管理
            </wd-button>
          </view>
        </template>
      </wd-card>
    </z-paging>
    <wd-popup v-model="dialog.visible" position="bottom" custom-class="yl-popup">
      <view class="action px-3">
        <wd-button type="text" @click="cancel">取消</wd-button>
        <wd-button type="text" @click="submit">确定</wd-button>
    </view>
    <!-- 新增杆包弹框 -->
    <wd-popup v-model="parentDialogVisible" position="bottom" custom-class="yl-popup">
      <view class="parent-dialog">
        <view class="dialog-header">
          <text class="dialog-title">新增杆包</text>
          <wd-icon name="close" class="close-icon" @click="closeParentDialog"></wd-icon>
        </view>
        <view class="dialog-content">
          <wd-cell-group>
            <wd-input
              v-model="newParentData.poleNumber"
              label="领用杆号"
              label-width="100px"
              placeholder="请输入领用杆号"
            />
            <wd-input
              v-model="newParentData.poleModel"
              label="杆型号"
              label-width="100px"
              placeholder="请输入杆型号"
            />
            <wd-input
              v-model="newParentData.polePackageNumber"
              label="杆包号"
              label-width="100px"
              placeholder="请输入杆包号"
            />
            <wd-input
              v-model="newParentData.poleWeight"
              label="杆重(kg)"
              label-width="100px"
              type="number"
              placeholder="请输入杆重"
            />
            <wd-picker
              v-model="newParentData.supplier"
              label="供应商"
              label-width="100px"
              :columns="supplierOptions"
              placeholder="请选择供应商"
            />
          </wd-cell-group>
        </view>
        <view class="dialog-footer">
          <wd-button plain @click="closeParentDialog">取消</wd-button>
          <wd-button type="primary" class="ml-2" @click="handleSaveNewParent">保存</wd-button>
        </view>
      </view>
      <WireForm ref="wireFormRef" />
    </wd-popup>
    <!-- Draw组件(领用自检) -->
    <wd-popup v-model="drawFormRef.visible" position="bottom" custom-class="yl-popup">
      <Draw
        :wire-id="drawData.wireId"
@@ -43,172 +183,324 @@
        @close="handleDrawClose"
      />
    </wd-popup>
    <wd-toast />
  </view>
</template>
<script setup lang="ts">
import CardTitle from "@/components/card-title/index.vue";
import WireForm from "./wireForm.vue";
import { useToast } from "wot-design-uni";
import ProductionCard from "../../components/ProductionCard.vue";
import zPaging from "@/components/z-paging/z-paging.vue";
import { useToast, dayjs } from "wot-design-uni";
import { onLoad } from "@dcloudio/uni-app";
import { onMounted, nextTick } from "vue";
import WireApi from "@/api/product/wire";
import ManageApi from "@/api/product/manage";
import Draw from "./rawMaterial.vue";
import { getTeamId } from "@/utils/cache";
import { useUserStore } from "@/store/modules/user";
import WireDetailApi from "@/api/product/wire";
const pagingRef = ref();
const wireFormRef = ref();
const paramsId = ref();
const toast = useToast();
const dialog = reactive({
  visible: false,
const userStore = useUserStore();
const paramsId = ref();
const model = ref();
const oneLength = ref();
// 父级数据列表
const parentDataList = ref<any[]>([]);
// 子级数据列表(所有子级数据的扁平化列表)
const childDataList = ref<any[]>([]);
// 供应商选项
const supplierOptions = ref<any[]>([]);
// 父级弹框相关
const parentDialogVisible = ref(false);
const newParentData = ref({
  poleNumber: "",
  poleModel: "",
  polePackageNumber: "",
  poleWeight: undefined as number | undefined,
  supplier: "",
  isConsumed: 1,
});
// Draw组件相关
const drawFormRef = reactive({
  visible: false,
});
// 处理draw组件关闭事件
const handleDrawClose = () => {
  // 确保弹窗被正确关闭
  drawFormRef.visible = false;
};
const drawData = ref({
  wireId: "",
  poleNumber: "",
});
const showDrawPopup = async () => {
  console.log("进入该方法!");
// 获取详情数据
const getDetailData = async (id: string) => {
  try {
    const { data } = await ManageApi.queryWireRawMaterialInspect({
      wireId: paramsId.value,
      poleNumber: drawData.value.poleNumber,
    });
    console.log("data", data);
    // 适配不同的数据结构返回格式
    if (data == null) {
      drawData.value = {
        wireId: paramsId.value,
        poleNumber: drawData.value.poleNumber,
      };
      // 显示Draw弹窗
      drawFormRef.visible = true;
      toast.success("请填写领用信息!");
    } else {
      // toast.error("已存在领用信息,无需填报!");
    const { data } = await WireDetailApi.getWireDetailById({ id });
    model.value = data.model;
    oneLength.value = data.oneLength;
  } catch (error) {
    console.error("获取详情失败:", error);
  }
};
// 加载供应商字典
const loadSupplierDict = async () => {
  try {
    const res = await ManageApi.dictAPI("al_supplier");
    if (res.data && Array.isArray(res.data)) {
      supplierOptions.value = res.data.map((item: any) => ({
        label: item.dictLabel || "",
        value: item.dictValue || item.value || "",
      }));
    }
  } catch (error) {
    console.error("获取领用信息失败:", error);
    toast.error("获取信息失败,请重试");
    console.error("加载供应商字典失败:", error);
  }
};
const cardAttr = ref<any[]>([
  {
    label: "领用杆号",
    prop: "poleNumber",
    span: 24,
  },
  {
    label: "单丝盘号",
    prop: "monofilamentNumber",
    span: 24,
  },
  {
    label: "杆型号",
    prop: "poleModel",
  },
  {
    label: "杆包号",
    prop: "polePackageNumber",
  },
  {
    label: "杆重(kg)",
    prop: "poleWeight",
  },
  {
    label: "规格型号",
    prop: "model",
  },
  {
    label: "盘型号",
    prop: "dishModel",
  },
  {
    label: "盘长(m)",
    prop: "oneLength",
  },
  {
    label: "实际长度",
    prop: "actuallyLength",
  },
  {
    label: "实际重量(kg)",
    prop: "actuallyWeight",
  },
]);
// 初始化数据
const getData = async () => {
  try {
    const { code, data } = await WireApi.getWireOutputTree({
      wireId: paramsId.value,
    });
const wireReportList = ref<any[]>([]);
    if (code == 200) {
      parentDataList.value = [];
      childDataList.value = [];
// const toEdit = () => {
//   uni.navigateTo({
//     url: "/pages/production/wire/report/wireEdit",
//   });
// };
      const parentMap = new Map();
const addReport = () => {
  dialog.visible = true;
};
      data.forEach((item: any) => {
        const parentKey = `${item.poleNumber}-${item.poleModel}-${item.polePackageNumber}`;
const submit = async () => {
  const result = await wireFormRef.value.submit();
  dialog.visible = !result.success;
  // 设置poleNumber到drawData中
  if (result.success) {
    drawData.value.poleNumber = result.poleNumber;
    showDrawPopup();
        if (!parentMap.has(parentKey)) {
          const parentData = {
            id: parentKey,
            poleNumber: item.poleNumber,
            poleModel: item.poleModel,
            polePackageNumber: item.polePackageNumber,
            dishModel: item.dishModel,
            poleWeight: item.poleWeight,
            supplier: item.supplier,
            isConsumed: item.isConsumed === true || item.isConsumed === 1 ? 1 : 0,
            treeId: item.id,
            isAutoAdd: item.isAutoAdd,
          };
          parentMap.set(parentKey, parentData);
          parentDataList.value.push(parentData);
        }
        if (item.node && Array.isArray(item.node)) {
          item.node.forEach((child: any) => {
            const childData = {
              ...child,
              parentKey: parentKey,
              poleNumber: item.poleNumber,
              poleModel: item.poleModel,
              polePackageNumber: item.polePackageNumber,
              supplier: item.supplier,
              selected: false,
            };
            childDataList.value.push(childData);
          });
        }
      });
    }
  } catch (error) {
    console.error("获取数据失败:", error);
    toast.error("获取数据失败");
  }
  pagingRef.value.reload();
};
const cancel = () => {
  toast.show("取消");
  dialog.visible = false;
// 新增父级数据 - 打开弹框
const handleAddParent = () => {
  const lastParent = parentDataList.value[0];
  // 初始化新数据,如果有最后一条数据,使用其值作为默认值
  newParentData.value = {
    poleNumber: lastParent?.poleNumber || "",
    poleModel: lastParent?.poleModel || "",
    polePackageNumber: lastParent?.polePackageNumber || "",
    poleWeight: lastParent?.poleWeight || null,
    supplier: lastParent?.supplier || "",
    isConsumed: 1,
  };
  parentDialogVisible.value = true;
};
const toAttachment = (item: any) => {
// 保存新父级数据
const handleSaveNewParent = async () => {
  if (
    !newParentData.value.poleNumber ||
    !newParentData.value.poleModel ||
    !newParentData.value.polePackageNumber ||
    !newParentData.value.poleWeight
  ) {
    toast.error("请填写完整的父级信息(领用杆号、杆型号、杆包号、杆重为必填项)");
    return;
  }
  try {
    const { code } = await WireApi.addRodBagTree({
      wireId: paramsId.value,
      poleNumber: newParentData.value.poleNumber,
      poleModel: newParentData.value.poleModel,
      polePackageNumber: newParentData.value.polePackageNumber,
      supplier: newParentData.value.supplier,
      poleWeight: newParentData.value.poleWeight,
      isConsumed: newParentData.value.isConsumed,
    });
    if (code == 200) {
      toast.success("保存成功");
      closeParentDialog();
      await getData();
    }
  } catch (error) {
    console.error("保存失败:", error);
    toast.error("保存失败");
  }
};
// 关闭父级弹框
const closeParentDialog = () => {
  parentDialogVisible.value = false;
  // 重置表单数据
  newParentData.value = {
    poleNumber: "",
    poleModel: "",
    polePackageNumber: "",
    poleWeight: undefined,
    supplier: "",
    isConsumed: 1,
  };
};
// 删除杆包
const handleDeleteRodBag = async (row: any) => {
  try {
    const res = await uni.showModal({
      title: "提示",
      content: `确定删除杆包:${row.poleNumber} - ${row.poleModel} - ${row.polePackageNumber} 吗?`,
    });
    if (res.confirm) {
      const { code } = await WireApi.deleteRodBagTree({
        wireId: paramsId.value,
        poleModel: row.poleModel,
        poleNumber: row.poleNumber,
        polePackageNumber: row.polePackageNumber,
      });
      if (code === 200) {
        toast.success("删除成功");
        await getData();
      } else {
        toast.error("删除失败");
      }
    }
  } catch (error) {
    console.error("删除杆包失败:", error);
    toast.error("删除失败");
  }
};
// 消耗情况变化
const handleConsumedChange = async (row: any, value: any) => {
  if (row.treeId) {
    // 保存旧值,用于失败时恢复
    const oldValue = row.isConsumed;
    // 处理 value,可能是数字、对象或其他格式
    let isConsumedValue: number;
    if (typeof value === "object" && value !== null && "value" in value) {
      // 如果是对象格式 {value: 1}
      isConsumedValue = value.value;
    } else if (typeof value === "number") {
      // 如果是数字
      isConsumedValue = value;
    } else if (typeof value === "boolean") {
      // 如果是布尔值
      isConsumedValue = value ? 1 : 0;
    } else {
      // 其他情况,尝试转换
      isConsumedValue = value === 1 || value === "1" || value === true ? 1 : 0;
    }
    // 先更新 UI
    row.isConsumed = isConsumedValue;
    try {
      const { code } = await WireApi.updateRodBagTree({
        treeId: row.treeId,
        isConsumed: isConsumedValue,
      });
      if (code != 200) {
        toast.error("更新失败");
        // 更新失败时恢复原值
        row.isConsumed = oldValue;
      }
    } catch (error) {
      console.error("更新消耗情况失败:", error);
      toast.error("更新失败");
      // 更新失败时恢复原值
      row.isConsumed = oldValue;
    }
  }
};
// 打开子级页面
const openChildDialog = async (parentRow: any) => {
  // 检查是否有领用信息
  try {
    const { code, data } = await ManageApi.queryWireRawMaterialInspect({
      wireId: paramsId.value,
      poleNumber: parentRow.poleNumber,
    });
    if (code == 200) {
      if (data == null) {
        // 显示Draw组件
        drawData.value = {
          wireId: paramsId.value,
          poleNumber: parentRow.poleNumber,
        };
        drawFormRef.visible = true;
        toast.warning("请先填写领用信息");
        return;
      }
    }
  } catch (error) {
    console.error("检查领用信息失败:", error);
  }
  // 跳转到报工管理页面
  uni.navigateTo({
    url: "/pages/production/wire/attachment/index",
    success: () => {
      // 页面跳转成功后发送事件传递数据
      uni.$emit("detailData", item);
    },
    url: `/pages/production/wire/report/reportManage?wireId=${paramsId.value}&parentId=${parentRow.id}&poleNumber=${parentRow.poleNumber}&poleModel=${parentRow.poleModel}&polePackageNumber=${parentRow.polePackageNumber}&poleWeight=${parentRow.poleWeight}&supplier=${parentRow.supplier || ""}`,
  });
};
const toCheck = (id: number) => {
  uni.navigateTo({
    url: `/pages/production/wire/selfInspect/index?id=${id}`,
  });
// 处理draw组件关闭事件
const handleDrawClose = () => {
  drawFormRef.visible = false;
};
// 获取拉丝报工列表
const getWireReportList = async () => {
  const { data } = await ManageApi.getReportList({
    wireId: paramsId.value,
    type: "拉丝",
  });
  pagingRef.value.complete(data);
};
onLoad((options: any) => {
onLoad(async (options: any) => {
  paramsId.value = options.id;
  await getDetailData(options.id);
  await loadSupplierDict();
  await getData();
});
</script>
<style lang="scss" scoped>
.list {
  height: calc(100vh - 30px);
  min-height: calc(100vh - 30px);
  padding: 12px;
  background: #f3f9f8;
@@ -219,8 +511,49 @@
  }
}
.action {
.parent-list {
  margin-top: 12px;
}
.card_bg {
  box-shadow: 0px 0px 12px 0px rgba(0, 0, 0, 0.05);
  padding-bottom: 10px;
  margin-bottom: 12px;
}
.icon_box {
  display: flex;
  justify-content: space-between;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  background: #e7f4ec99;
  border-radius: 50%;
}
.edit-form {
  padding: 12px 0;
}
.parent-dialog {
  max-height: 80vh;
  display: flex;
  flex-direction: column;
  background: #fff;
  border-radius: 12px 12px 0 0;
}
.dialog-content {
  flex: 1;
  overflow-y: auto;
  padding: 16px;
}
.dialog-footer {
  display: flex;
  justify-content: flex-end;
  padding: 16px;
  border-top: 1px solid #e6e6e6;
  gap: 8px;
}
</style>