spring
2026-07-31 a8cc9d60a80afd7362e1d0fd31fb4307a6e04e2e
fix: 芯线分层领用
已添加1个文件
已修改4个文件
794 ■■■■■ 文件已修改
src/api/product/twist.ts 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages.json 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/production/twist/components/SteelCoreCard.vue 157 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/production/twist/receive/steelCore/form.vue 137 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/production/twist/receive/steelCore/index.vue 485 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/product/twist.ts
@@ -72,6 +72,15 @@
    });
  },
  // èŽ·å–é’¢èŠ¯é¢†ç”¨å±‚çº§æ•°æ®ï¼ˆå‚ç…§PC端 getSteelCoreDishTypeByWire)
  getSteelCoreDishTypeByWire(wireId: number) {
    return request<BaseResult<any>>({
      url: "/strandedWire/getSteelCoreDishTypeByWire",
      method: "POST",
      data: wireId,
    });
  },
  // æ ¹æ®å•丝编号查询
  selectByMonofilamentNumber(params: { monofilamentNumber: string }) {
    return request<BaseResult<any>>({
src/pages.json
@@ -248,12 +248,6 @@
      }
    },
    {
      "path": "pages/production/twist/receive/steelCore/edit",
      "style": {
        "navigationBarTitleText": "绞线钢芯编辑"
      }
    },
    {
      "path": "pages/production/twist/selfInspect/index",
      "style": {
        "navigationBarTitleText": "绞线自检"
src/pages/production/twist/components/SteelCoreCard.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,157 @@
<template>
  <view class="swipe-container">
    <view
      class="swipe-content"
      :style="{ transform: `translateX(${translateX}px)` }"
      @touchstart="handleTouchStart"
      @touchmove="handleTouchMove"
      @touchend="handleTouchEnd"
    >
      <wd-card>
        <wd-cell-group :border="true">
          <wd-cell title="芯线类型" :value="data.diskMaterial || '-'" />
          <wd-cell title="规格型号" :value="data.model || '-'" />
          <wd-cell title="盘号" :value="data.monofilamentNumber || '-'" />
          <wd-cell title="数量" :value="formatAmount" />
          <wd-cell title="重量" :value="formatWeight" />
          <wd-cell title="厂家" :value="data.supplier || '-'" />
        </wd-cell-group>
      </wd-card>
    </view>
    <view class="swipe-delete" @click="handleDelete">
      <text class="delete-text">删除</text>
    </view>
  </view>
</template>
<script setup lang="ts">
import { ref, computed } from "vue";
const props = defineProps({
  data: {
    type: Object,
    default: () => ({}),
  },
});
const emit = defineEmits(["delete", "swipe-open"]);
const translateX = ref(0);
const startX = ref(0);
const startY = ref(0);
const currentX = ref(0);
const isSwipeOpen = ref(false);
const deleteWidth = 80;
const isHorizontalSwipe = ref(false);
const formatAmount = computed(() => {
  const val = props.data.amount;
  if (val === undefined || val === null || val === "") return "-";
  return `${val} ${props.data.unit || ""}`;
});
const formatWeight = computed(() => {
  const val = props.data.weight;
  if (val === undefined || val === null || val === "") return "-";
  const unit = props.data.weightUnit || "kg";
  return `${val} ${unit}`;
});
const handleTouchStart = (e: any) => {
  startX.value = e.touches[0].clientX;
  startY.value = e.touches[0].clientY;
  currentX.value = translateX.value;
  isHorizontalSwipe.value = false;
};
const handleTouchMove = (e: any) => {
  const moveX = e.touches[0].clientX - startX.value;
  const moveY = e.touches[0].clientY - startY.value;
  if (!isHorizontalSwipe.value && Math.abs(moveX) > Math.abs(moveY) && Math.abs(moveX) > 10) {
    isHorizontalSwipe.value = true;
  }
  if (isHorizontalSwipe.value) {
    e.stopPropagation();
    const newTranslateX = currentX.value + moveX;
    if (newTranslateX <= 0 && newTranslateX >= -deleteWidth) {
      translateX.value = newTranslateX;
    } else if (newTranslateX < -deleteWidth) {
      translateX.value = -deleteWidth;
    } else if (newTranslateX > 0) {
      translateX.value = 0;
    }
  }
};
const handleTouchEnd = (e: any) => {
  if (isHorizontalSwipe.value) {
    e.stopPropagation();
    if (translateX.value < -deleteWidth / 2) {
      translateX.value = -deleteWidth;
      isSwipeOpen.value = true;
      emit("swipe-open", props.data);
    } else {
      translateX.value = 0;
      isSwipeOpen.value = false;
    }
  }
  isHorizontalSwipe.value = false;
};
const handleDelete = () => {
  translateX.value = 0;
  isSwipeOpen.value = false;
  emit("delete", props.data);
};
const closeSwipe = () => {
  if (isSwipeOpen.value) {
    translateX.value = 0;
    isSwipeOpen.value = false;
  }
};
defineExpose({
  closeSwipe,
  isSwipeOpen,
});
</script>
<style lang="scss" scoped>
.swipe-container {
  position: relative;
  overflow: hidden;
  margin-bottom: 8px;
}
.swipe-content {
  position: relative;
  transition: transform 0.3s ease;
  z-index: 2;
  background: #fff;
  touch-action: pan-y;
}
.swipe-delete {
  position: absolute;
  right: 0;
  top: 12px;
  bottom: 12px;
  width: 80px;
  background: #ff4444;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1;
  border-radius: 4px;
  box-shadow: 0px 0px 12px 0px rgba(0, 0, 0, 0.05);
  .delete-text {
    color: #fff;
    font-size: 14px;
    font-weight: 500;
  }
}
</style>
src/pages/production/twist/receive/steelCore/form.vue
@@ -21,7 +21,7 @@
      />
      <wd-input
        v-model="model.monofilamentNumber"
        label="样品编号"
        label="盘号"
        label-width="100px"
        prop="monofilamentNumber"
        clearable
@@ -33,7 +33,7 @@
        label-width="100px"
        prop="amount"
        clearable
        placeholder="请输入长度"
        placeholder="请输入数量"
      />
      <wd-input
        v-model="model.weight"
@@ -60,7 +60,6 @@
<script lang="ts" setup>
import { onMounted, watch } from "vue";
import useFormData from "@/hooks/useFormData";
import TwistApi from "@/api/product/twist";
import ManageApi from "@/api/product/manage";
import { useToast } from "wot-design-uni";
@@ -80,14 +79,11 @@
});
const emits = defineEmits(["refresh"]);
const paramsId = ref();
const editId = ref(); // ç¼–辑时的ID
const allListData = ref<any[]>([]); // å­˜å‚¨å®Œæ•´åˆ—表数据
const toast = useToast();
const { form: model } = useFormData({
  diskMaterial: undefined, // èŠ¯çº¿ç±»åž‹
  model: undefined, // è§„格型号
  monofilamentNumber: undefined, // æ ·å“ç¼–号
  monofilamentNumber: undefined, // ç›˜å·
  amount: undefined, // æ•°é‡
  weight: undefined, // é‡é‡
  supplier: undefined, // åނ家
@@ -150,39 +146,9 @@
  { immediate: true }
);
// æ–°å¢žæäº¤
const submit = async () => {
  const currentWireId = props.wireId || paramsId.value;
  const { code } = await TwistApi.addStrandedWireDish([
    {
      wireId: currentWireId,
      ...model,
    },
  ]);
  if (code == 200) {
    toast.success("新增成功");
    emits("refresh");
    return true;
  }
  return false;
};
// ç¼–辑提交(也走新增接口,提交整个列表)
const submitEdit = async (list?: any[], id?: number) => {
  const currentList = list || allListData.value;
  const currentId = id || editId.value;
  if (!currentId) {
    toast.error("缺少记录ID");
    return false;
  }
  // æ›´æ–°åˆ—表中对应的数据项
  const updatedList = currentList.map((item) => {
    if (item.id === currentId) {
      // ä¿ç•™åŽŸæœ‰æ•°æ®ï¼Œç„¶åŽæ›´æ–°ä¿®æ”¹çš„å­—æ®µ
      const updatedItem = {
        ...item, // å…ˆä¿ç•™åŽŸæœ‰çš„æ‰€æœ‰æ•°æ®
// æ”¶é›†è¡¨å•数据(不调 API,返回给父组件处理)
const collectData = () => {
  return {
        diskMaterial: model.diskMaterial,
        model: model.model,
        monofilamentNumber: model.monofilamentNumber,
@@ -191,64 +157,17 @@
        supplier: model.supplier,
        type: model.type,
      };
      return updatedItem;
    }
    return item;
  });
  // æäº¤æ•´ä¸ªåˆ—表
  const { code } = await TwistApi.addStrandedWireDish(updatedList);
  if (code == 200) {
    toast.success("更新成功");
    return true;
  }
  return false;
};
// è®¾ç½®è¡¨å•数据(用于编辑时回显)
const setFormData = (list: any[], currentEditId: number) => {
  // å®‰å…¨æ£€æŸ¥ï¼šç¡®ä¿list是数组
  if (!Array.isArray(list)) {
    return;
  }
  // å­˜å‚¨å®Œæ•´åˆ—表数据
  allListData.value = list;
  editId.value = currentEditId;
  // æ‰¾åˆ°å½“前编辑项并回显到表单
  const currentItem = list.find((item) => item.id === currentEditId);
  if (currentItem) {
    model.diskMaterial = currentItem.diskMaterial;
    model.model = currentItem.model;
    model.monofilamentNumber = currentItem.monofilamentNumber;
    model.amount = currentItem.amount;
    model.weight = currentItem.weight;
    model.supplier = currentItem.supplier;
    model.type = currentItem.type || "钢芯";
    // è®¾ç½®èŠ¯çº¿ç±»åž‹çš„å›žæ˜¾å€¼
    diskMaterialValue.value = currentItem.diskMaterial || "";
  }
// æ–°å¢žæäº¤ï¼ˆå…¼å®¹æ—§æ¨¡å¼ï¼Œçˆ¶ç»„件可调用)
const submit = async () => {
  return collectData();
};
// ç›‘听编辑数据变化,自动回显
watch(
  () => props.editData,
  (newData) => {
    if (newData && props.mode === "edit") {
      model.diskMaterial = newData.diskMaterial || "";
      model.model = newData.model || "";
      model.monofilamentNumber = newData.monofilamentNumber || "";
      model.amount = newData.amount || "";
      model.weight = newData.weight || "";
      model.supplier = newData.supplier || "";
      model.type = newData.type || "钢芯";
      diskMaterialValue.value = newData.diskMaterial || "";
    }
  },
  { immediate: true, deep: true }
);
// ç¼–辑提交(兼容旧模式,不调API,返回表单数据)
const submitEdit = async (list?: any[], id?: number) => {
  return collectData();
};
// é‡ç½®è¡¨å•数据
const resetFormData = () => {
@@ -268,7 +187,7 @@
    model.diskMaterial = data.diskMaterial || "";
    model.model = data.model || "";
    model.monofilamentNumber = data.monofilamentNumber || "";
    model.amount = data.oneLength || data.amount || "";
    model.amount = data.amount || data.oneLength || "";
    model.weight = data.weight || "";
    model.supplier = data.supplier || "";
    model.type = data.type || "钢芯";
@@ -276,9 +195,30 @@
  }
};
onLoad((options: any) => {
  paramsId.value = options.id;
});
// è®¾ç½®è¡¨å•数据(用于编辑时回显,兼容 edit.vue)
const setFormData = (item: any) => {
  if (item) {
    model.diskMaterial = item.diskMaterial || "";
    model.model = item.model || "";
    model.monofilamentNumber = item.monofilamentNumber || "";
    model.amount = item.amount || "";
    model.weight = item.weight || "";
    model.supplier = item.supplier || "";
    model.type = item.type || "钢芯";
    diskMaterialValue.value = item.diskMaterial || "";
  }
};
// ç›‘听编辑数据变化,自动回显
watch(
  () => props.editData,
  (newData) => {
    if (newData && props.mode === "edit") {
      setFormData(newData);
    }
  },
  { immediate: true, deep: true }
);
onMounted(async () => {
  await loadDiskMaterialDict();
@@ -288,6 +228,7 @@
defineExpose({
  submit,
  submitEdit,
  collectData,
  setFormData,
  resetFormData,
  fillFormData,
src/pages/production/twist/receive/steelCore/index.vue
@@ -1,53 +1,55 @@
<template>
  <view class="list">
  <view class="list_box">
    <z-paging
      ref="pagingRef"
      v-model="cardList"
      :fixed="false"
      :auto-show-back-to-top="true"
      :loading-more-enabled="false"
      @query="getList"
    >
      <template #top>
        <CardTitle title="芯线领用" :hideAction="false" :full="false">
        <CardTitle title="芯线领用" :hideAction="false">
          <template #action>
            <wd-button type="icon" icon="scan" color="#0D867F" @click="openScan"></wd-button>
            <wd-button type="icon" icon="add-circle" color="#0D867F" @click="addReport"></wd-button>
            <wd-button type="icon" icon="add-circle" color="#0D867F" @click="openAddForm"></wd-button>
          </template>
        </CardTitle>
      </template>
      <wd-card v-for="(item, index) in cardList" :key="index" type="rectangle" custom-class="round">
        <template #title>
          <view class="flex justify-between">
            <view>
              <wd-icon name="a-rootlist" color="#0D867F"></wd-icon>
              <text class="text-[#252525] ml-2 font-medium">{{ item.model }}</text>
            </view>
            <view class="text-[#A8A8A8]" @click="toEdit(item.id)">编辑</view>
      <!-- å±‚级 tabs -->
      <wd-tabs v-model="tab" slidable="always" class="tabs-container">
        <block v-for="item in nodeList" :key="item.twistedLayer">
          <wd-tab :title="item.twistedLayer" :name="item.twistedLayer">
            <scroll-view class="content" scroll-y>
              <SteelCoreCard
                v-for="(m, i) in item.strandedWireDish"
                :key="i"
                :data="m"
                @delete="handleDeleteCard(item, m)"
              />
            </scroll-view>
          </wd-tab>
        </block>
      </wd-tabs>
      <template #bottom>
        <view class="flex justify-center items-center">
          <wd-button block @click="save">
            <text class="text-[#fff]">保存</text>
          </wd-button>
          </view>
        </template>
        <ProductionCard :data="cardAttr" :value="item" color="#0D867F" />
      </wd-card>
    </z-paging>
    <wd-popup v-model="addDialog.visible" position="bottom" custom-class="yl-popup">
    <!-- æ–°å¢žé’¢èŠ¯å¼¹çª— -->
    <wd-popup v-model="showAddForm" position="bottom" custom-class="yl-popup">
      <view class="action px-3">
        <wd-button type="text" @click="cancelAdd">取消</wd-button>
        <wd-button type="text" @click="submitAdd">确定</wd-button>
      </view>
      <SteelCore ref="addFormRef" mode="add" :wireId="paramsId" @refresh="reloadList" />
      <SteelCoreForm ref="addFormRef" mode="add" :wireId="paramsId" />
    </wd-popup>
    <wd-popup v-model="editDialog.visible" position="bottom" custom-class="yl-popup">
      <view class="action px-3">
        <wd-button type="text" @click="cancelEdit">取消</wd-button>
        <wd-button type="text" @click="submitEdit">确定</wd-button>
      </view>
      <SteelCore
        ref="editFormRef"
        mode="edit"
        :wireId="paramsId"
        :editData="editDialog.currentItem"
        @refresh="reloadList"
      />
    </wd-popup>
    <Scan ref="scanRef" emitName="scanSteelCore" />
    <wd-toast />
  </view>
@@ -55,11 +57,10 @@
<script setup lang="ts">
import CardTitle from "@/components/card-title/index.vue";
import ProductionCard from "../../../components/ProductionCard.vue";
import SteelCoreCard from "../../components/SteelCoreCard.vue";
import SteelCoreForm from "./form.vue";
import { useToast } from "wot-design-uni";
import SteelCore from "./form.vue";
import { onLoad, onUnload, onShow, onHide } from "@dcloudio/uni-app";
import ManageApi from "@/api/product/manage";
import TwistApi from "@/api/product/twist";
import zPaging from "@/components/z-paging/z-paging.vue";
import Scan from "@/components/scan/index.vue";
@@ -67,174 +68,306 @@
const paramsId = ref();
const pagingRef = ref();
const addFormRef = ref();
const editFormRef = ref();
const scanRef = ref();
const toast = useToast();
const isPageVisible = ref(false); // æ ‡è®°é¡µé¢æ˜¯å¦å¯è§
const addDialog = reactive({
  visible: false,
});
const editDialog = reactive({
  visible: false,
  currentItem: null as any,
  editId: undefined as number | undefined,
});
const cardList = ref<any[]>([]);
const tab = ref("");
const nodeList = ref<any[]>([]);
const showAddForm = ref(false);
const isPageVisible = ref(false);
const cardAttr = ref<any[]>([
  {
    label: "样品编号",
    prop: "monofilamentNumber",
  },
  {
    label: "数量",
    prop: "amount",
    unitProp: "unit",
  },
  {
    label: "重量",
    prop: "weight",
    unitProp: "weightUnit",
  },
  {
    label: "厂家",
    prop: "supplier",
    span: 16,
  },
]);
// ç›‘听标签切换
watch(tab, () => {
  if (tab.value) {
    getList();
  }
});
const toEdit = (id: number) => {
  const itemToEdit = cardList.value.find((item) => item.id === id);
  if (itemToEdit) {
    editDialog.currentItem = itemToEdit;
    editDialog.editId = id;
    editDialog.visible = true;
// èŽ·å–é’¢èŠ¯å±‚çº§æ•°æ®ï¼ˆå‚ç…§PC端 getSteelCoreDishTypeByWire)
const fetchSteelCoreData = async (wireId: number) => {
  const { code, data, msg } = await TwistApi.getSteelCoreDishTypeByWire(wireId);
  if (code === 200 && data) {
    nodeList.value = data.nodeList || [];
    // è¿½åŠ "其他"层
    if (data.otherStrandedWireDish && data.otherStrandedWireDish.length > 0) {
      nodeList.value.push({
        strandedWireDish: data.otherStrandedWireDish,
        twistedLayer: "其他",
        twistId: null,
      });
    }
    // è®¾ç½®é»˜è®¤ç¬¬ä¸€å±‚
    if (nodeList.value.length > 0 && !tab.value) {
      tab.value = nodeList.value[0].twistedLayer;
      getList();
    }
  } else {
    toast.error(msg || "获取钢芯层级数据失败");
  }
};
const addReport = () => {
// ä»Žå½“前选中层获取列表数据
const getList = async () => {
  const currentLayer = nodeList.value.find((node) => node.twistedLayer === tab.value);
  if (currentLayer && currentLayer.strandedWireDish) {
    pagingRef.value.complete(currentLayer.strandedWireDish);
  } else {
    pagingRef.value.complete([]);
  }
};
// æ‰“开新增表单
const openAddForm = () => {
  if (!tab.value) {
    toast.error("请先选择一个层");
    return;
  }
  if (addFormRef.value) {
    addFormRef.value.resetFormData();
  }
  addDialog.visible = true;
  showAddForm.value = true;
};
// æäº¤æ–°å¢ž
const submitAdd = async () => {
  const success = await addFormRef.value.submit();
  if (success) {
    addDialog.visible = false;
  const formData = await addFormRef.value.submit();
  if (!formData) return;
  // æŸ¥æ‰¾å½“前层
  const currentLayer = nodeList.value.find((node) => node.twistedLayer === tab.value);
  if (!currentLayer) {
    toast.error("未找到当前选中的层");
    return;
  }
  // åŒå±‚重复检查
  if (formData.monofilamentNumber) {
    const exists = currentLayer.strandedWireDish?.some(
      (item: any) => item.monofilamentNumber === formData.monofilamentNumber
    );
    if (exists) {
      toast.error("该钢芯已领用,请勿重复添加");
      return;
    }
  }
  // æ·»åŠ åˆ°å½“å‰å±‚
  if (!currentLayer.strandedWireDish) {
    currentLayer.strandedWireDish = [];
  }
  currentLayer.strandedWireDish.push({
    ...formData,
    wireId: paramsId.value,
  });
  getList();
  showAddForm.value = false;
  toast.success("添加成功");
};
const cancelAdd = () => {
  toast.show("取消");
  addDialog.visible = false;
  showAddForm.value = false;
};
const submitEdit = async () => {
  const success = await editFormRef.value.submitEdit(cardList.value, editDialog.editId);
  if (success) {
    editDialog.visible = false;
    reloadList();
  }
};
const cancelEdit = () => {
  toast.show("取消");
  editDialog.visible = false;
};
const getList = async () => {
  const { code, data } = await ManageApi.getStrandedWireDish({
    wireId: paramsId.value,
    type: "钢芯",
  });
  if (code == 200) {
    pagingRef.value.complete(data);
  }
};
const reloadList = () => {
  pagingRef.value.refresh();
};
// æ‰«ç ç›¸å…³æ–¹æ³•
const openScan = () => {
  scanRef.value.triggerScan();
};
// èŽ·å–æ‰«ç æ•°æ®
const getScanCode = async (code: any) => {
  // æ£€æŸ¥é¡µé¢æ˜¯å¦å¯è§ï¼Œå¦‚果不可见则不处理扫码数据
  if (!isPageVisible.value) {
    return;
  }
  try {
    const parseData = JSON.parse(code.code);
    // æ£€æŸ¥å¿…需字段:model、supplier、diskMaterial
    const requiredFields = ["model", "supplier", "diskMaterial"];
    const missingFields = requiredFields.filter((field) => !parseData[field]);
    if (missingFields.length > 0) {
      toast.error(`二维码错误,请更换二维码!`);
    if (!tab.value) {
      toast.error("请先选择一个层");
      return;
    }
    // æ‰“开新增弹框并填充扫码获取的信息
    addDialog.visible = true;
    // ç­‰å¾…弹框打开后填充表单数据
    // ä½¿ç”¨åŒé‡ç­‰å¾…:nextTick + setTimeout ç¡®ä¿ç»„件已完全挂载
    nextTick(() => {
      setTimeout(() => {
        if (addFormRef.value) {
          addFormRef.value.fillFormData(parseData);
          toast.success("扫码成功,请确认信息");
        } else {
          toast.error("表单加载失败,请重试");
    const currentLayer = nodeList.value.find((node) => node.twistedLayer === tab.value);
    if (!currentLayer) {
      toast.error("未找到当前选中的层");
      return;
        }
      }, 200); // å»¶è¿Ÿ200ms确保弹框和组件已完全渲染
    });
    const parseData = JSON.parse(code.code);
    // æ£€æŸ¥å¿…需字段
    const requiredFields = ["model", "supplier", "diskMaterial"];
    const missingFields = requiredFields.filter((field) => !parseData[field]);
    if (missingFields.length > 0) {
      toast.error("二维码错误,请更换二维码!");
      return;
    }
    // åŒå±‚重复检查
    if (parseData.monofilamentNumber) {
      const exists = currentLayer.strandedWireDish?.some(
        (item: any) => item.monofilamentNumber === parseData.monofilamentNumber
      );
      if (exists) {
        toast.error("该钢芯已领用,请勿重复扫码");
        return;
      }
    }
    // æž„建新钢芯数据
    const newItem = {
      wireId: paramsId.value,
      diskMaterial: parseData.diskMaterial || "",
      model: parseData.model || "",
      monofilamentNumber: parseData.monofilamentNumber || "",
      amount: parseData.oneLength || parseData.amount || "",
      weight: parseData.weight || "",
      supplier: parseData.supplier || "",
      type: "钢芯",
    };
    if (!currentLayer.strandedWireDish) {
      currentLayer.strandedWireDish = [];
    }
    currentLayer.strandedWireDish.push(newItem);
    getList();
    toast.success("扫码成功");
  } catch (error) {
    toast.error("二维码异常,请更换二维码!");
  }
};
onLoad((options: any) => {
  // å¼€å¯å¹¿æ’­ç›‘听事件
// æ‰“开扫描
const openScan = () => {
  scanRef.value.triggerScan();
};
// ä¿å­˜ï¼ˆæ‰¹é‡æäº¤ï¼‰
const save = () => {
  // æ£€æŸ¥æ˜¯å¦æœ‰æ–°æ•°æ®éœ€è¦ä¿å­˜
  let hasNewData = false;
  let newCount = 0;
  nodeList.value.forEach((node) => {
    if (node.strandedWireDish && Array.isArray(node.strandedWireDish)) {
      const hasNewInLayer = node.strandedWireDish.some(
        (item: { id?: number }) => item.id === undefined || item.id === null
      );
      if (hasNewInLayer) {
        hasNewData = true;
        newCount += node.strandedWireDish.filter(
          (item: { id?: number }) => item.id === undefined || item.id === null
        ).length;
      }
    }
  });
  if (!hasNewData) {
    toast.error("没有新的钢芯数据需要保存");
    return;
  }
  // ç¡®è®¤ä¿å­˜
  uni.showModal({
    title: "提示",
    content: `确认保存 ${newCount} æ¡é’¢èŠ¯é¢†ç”¨æ•°æ®å—ï¼Ÿ`,
    success: async (res) => {
      if (res.confirm) {
        await handleConfirmSave();
      }
    },
  });
};
// æ‰§è¡Œæ‰¹é‡ä¿å­˜
const handleConfirmSave = async () => {
  const newData: any[] = [];
  nodeList.value.forEach((node) => {
    // é™„加上下级 twistId
    if (node.strandedWireDish && Array.isArray(node.strandedWireDish)) {
      node.strandedWireDish.forEach((item: any) => {
        item.saleTwistId = node.twistId;
      });
      const layerNewData = node.strandedWireDish.filter(
        (item: { id?: number }) => item.id === undefined || item.id === null
      );
      newData.push(...layerNewData);
    }
  });
  if (newData.length === 0) {
    toast.error("没有新的钢芯数据需要保存");
    return;
  }
  const { code, msg } = await TwistApi.addStrandedWireDish(newData);
  if (code == 200) {
    toast.success(msg || "保存成功");
    // åˆ·æ–°æ•°æ®èŽ·å–æœ€æ–°çš„ id
    fetchSteelCoreData(paramsId.value);
  } else {
    toast.error(msg || "保存失败");
  }
};
// åˆ é™¤å¡ç‰‡
const handleDeleteCard = async (layer: any, cardData: any) => {
  uni.showModal({
    title: "提示",
    content: "确定要删除该钢芯吗?",
    success: async (res) => {
      if (res.confirm) {
        try {
          // å·²ä¿å­˜çš„æ•°æ®è°ƒç”¨æŽ¥å£åˆ é™¤
          if (cardData.id !== undefined && cardData.id !== null) {
            const { code, msg } = await TwistApi.deleteStrandedWireDish(cardData.id);
            if (code !== 200) {
              toast.error(msg || "删除失败");
              return;
            }
          }
          // å‰ç«¯ç§»é™¤
          if (layer.strandedWireDish && Array.isArray(layer.strandedWireDish)) {
            const index = layer.strandedWireDish.findIndex(
              (item: any) => item.monofilamentNumber === cardData.monofilamentNumber
            );
            if (index !== -1) {
              layer.strandedWireDish.splice(index, 1);
              toast.success("删除成功");
              getList();
            }
          }
        } catch (error: any) {
          toast.error(error.msg || "删除失败");
        }
      }
    },
  });
};
onLoad(async (options: any) => {
  uni.$on("scanSteelCore", getScanCode);
  paramsId.value = options.id;
  fetchSteelCoreData(options.id);
});
onShow(() => {
  // é¡µé¢æ˜¾ç¤ºæ—¶æ ‡è®°ä¸ºå¯è§
  isPageVisible.value = true;
});
onHide(() => {
  // é¡µé¢éšè—æ—¶æ ‡è®°ä¸ºä¸å¯è§
  isPageVisible.value = false;
});
onUnload(() => {
  // å–消广播监听事件
  uni.$off("scanSteelCore", getScanCode);
  isPageVisible.value = false;
});
</script>
<style lang="scss" scoped>
.list {
  height: calc(100vh - 120px);
  padding: 12px;
.list_box {
  height: calc(100vh - 50px);
  background: #f3f9f8;
  :deep() {
    .round {
      border-radius: 4px;
    }
  }
  display: flex;
  flex-direction: column;
}
.action {
@@ -245,4 +378,64 @@
:deep(.wd-button__content) {
  color: #0d867f;
}
.tabs-container {
  height: calc(100vh - 200px);
  display: flex;
  flex-direction: column;
}
.content {
  height: calc(100vh - 200px);
  width: 100%;
}
:deep(.zp-paging-container) {
  background: transparent !important;
  flex: 1;
  display: flex;
  flex-direction: column;
}
:deep(.zp-paging-container-content) {
  background: transparent !important;
  flex: 1;
  display: flex;
  flex-direction: column;
}
:deep(.wd-tabs) {
  background: transparent !important;
  height: 100%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
:deep(.wd-tabs__nav) {
  margin-bottom: 10px;
  flex-shrink: 0;
  position: sticky;
  top: 0;
  z-index: 10;
  background: #f3f9f8;
}
:deep(.wd-tabs__content) {
  flex: 1;
  overflow: visible;
}
:deep(.wd-tab__pane) {
  height: 100%;
}
:deep(.zp-paging-container-top) {
  flex-shrink: 0;
}
:deep(.zp-paging-container-bottom) {
  flex-shrink: 0;
  padding: 8px 12px;
}
</style>