<template> 
 | 
  <view class="list_box"> 
 | 
    <z-paging 
 | 
      ref="pagingRef" 
 | 
      :fixed="false" 
 | 
      :auto-show-back-to-top="true" 
 | 
      :loading-more-enabled="false" 
 | 
      @query="getList" 
 | 
    > 
 | 
      <template #top> 
 | 
        <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="openManualInput" 
 | 
            ></wd-button> 
 | 
          </template> 
 | 
        </CardTitle> 
 | 
      </template> 
 | 
      <!-- <MonofilCard v-for="(item, index) in cardList" :key="index" :data="item" /> --> 
 | 
      <wd-tabs v-model="tab" slidable="always" class="tabs-container"> 
 | 
        <block v-for="item in nodeList" :key="item"> 
 | 
          <wd-tab :title="item.twistedLayer" :name="item.twistedLayer"> 
 | 
            <scroll-view class="content" scroll-y> 
 | 
              <MonofilCard v-for="(m, i) in item.strandedWireDish" :key="i" :data="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> 
 | 
    </z-paging> 
 | 
    <Scan ref="scanRef" emitName="scanMono" /> 
 | 
    <StatisticsModal 
 | 
      v-model:visible="showStatisticsModal" 
 | 
      :nodeList="nodeList" 
 | 
      @confirm="handleConfirmSave" 
 | 
    /> 
 | 
  
 | 
    <!-- 手动输入质量追溯号弹框 --> 
 | 
    <wd-popup v-model="showManualInput" position="center" :close-on-click-modal="false"> 
 | 
      <view class="manual-input-modal"> 
 | 
        <view class="modal-header"> 
 | 
          <text class="title">手动领用单丝</text> 
 | 
          <wd-icon name="close" @click="closeManualInput" /> 
 | 
        </view> 
 | 
        <view class="modal-content"> 
 | 
          <view class="input-label">单丝编号</view> 
 | 
          <wd-input 
 | 
            v-model="manualOutPutId" 
 | 
            placeholder="请输入单丝编号" 
 | 
            clearable 
 | 
            @clear="manualOutPutId = ''" 
 | 
          /> 
 | 
        </view> 
 | 
        <view class="modal-footer"> 
 | 
          <wd-button @click="closeManualInput" type="default">取消</wd-button> 
 | 
          <wd-button type="primary" @click="handleManualConfirm" custom-class="confirm-btn"> 
 | 
            确定 
 | 
          </wd-button> 
 | 
        </view> 
 | 
      </view> 
 | 
    </wd-popup> 
 | 
  
 | 
    <wd-toast /> 
 | 
  </view> 
 | 
</template> 
 | 
  
 | 
<script setup lang="ts"> 
 | 
import CardTitle from "@/components/card-title/index.vue"; 
 | 
import MonofilCard from "../components/MonofilCard.vue"; 
 | 
import StatisticsModal from "../components/StatisticsModal.vue"; 
 | 
import { useToast } from "wot-design-uni"; 
 | 
import { onLoad, onUnload } from "@dcloudio/uni-app"; 
 | 
import Scan from "@/components/scan/index.vue"; 
 | 
import ManageApi from "@/api/product/manage"; 
 | 
import TwistApi from "@/api/product/twist"; 
 | 
import zPaging from "@/components/z-paging/z-paging.vue"; 
 | 
// import { useZebraScan } from "@/hooks/useZebraScan"; 
 | 
// const { init, start, stop, triggerScan } = useZebraScan(); 
 | 
  
 | 
const paramsId = ref(); 
 | 
const pagingRef = ref(); 
 | 
const scanRef = ref(); 
 | 
const toast = useToast(); 
 | 
const tab = ref(""); 
 | 
const showStatisticsModal = ref(false); 
 | 
const showManualInput = ref(false); 
 | 
const manualOutPutId = ref(""); 
 | 
  
 | 
// 监听标签切换 
 | 
watch(tab, () => { 
 | 
  if (tab.value) { 
 | 
    console.log("tab.value:===========1", tab.value); 
 | 
    getList(); 
 | 
  } 
 | 
}); 
 | 
  
 | 
const getScanCode = async (code: any) => { 
 | 
  console.log("自定义扫描的结果回调函数:", code); 
 | 
  // let parseData = code.trim(); 
 | 
  console.log("code:===========", JSON.parse(code.code)); 
 | 
  console.log("id:=============", JSON.parse(code.code).id); 
 | 
  try { 
 | 
    // 检查是否已选择标签 
 | 
    if (!tab.value) { 
 | 
      toast.error("请先选择一个层"); 
 | 
      return; 
 | 
    } 
 | 
  
 | 
    // 找到当前选中的层 
 | 
    console.log("tab.value:===========2", tab.value); 
 | 
    const currentLayer = nodeList.value.find((node) => node.twistedLayer === tab.value); 
 | 
    if (!currentLayer) { 
 | 
      toast.error("未找到当前选中的层"); 
 | 
      return; 
 | 
    } 
 | 
    console.log("tab.value:===========3", currentLayer); 
 | 
    const { data } = await TwistApi.getScarn({ 
 | 
      outPutId: JSON.parse(code.code).id, 
 | 
      twistId: currentLayer.twistId, 
 | 
    }); 
 | 
  
 | 
    // 检查当前层是否已存在该单丝 
 | 
    const exists = currentLayer.strandedWireDish?.some( 
 | 
      (item: any) => item.monofilamentNumber === data.monofilamentNumber 
 | 
    ); 
 | 
    if (!exists) { 
 | 
      const { id, outPutId, wireId, oneLength, ...rest } = data; 
 | 
      const newItem = { 
 | 
        wireId: paramsId.value, 
 | 
        outputId: id, 
 | 
        amount: oneLength, 
 | 
        ongLength: oneLength, 
 | 
        ...rest, 
 | 
      }; 
 | 
  
 | 
      // 添加到当前层的 strandedWireDish 中 
 | 
      if (!currentLayer.strandedWireDish) { 
 | 
        currentLayer.strandedWireDish = []; 
 | 
      } 
 | 
      currentLayer.strandedWireDish.push(newItem); 
 | 
  
 | 
      // 刷新当前层的数据显示 
 | 
      getList(); 
 | 
    } else { 
 | 
      toast.error("该单丝已领用,请勿重复扫码"); 
 | 
    } 
 | 
  } catch (error) { 
 | 
    toast.error("二维码异常,请更换二维码!"); 
 | 
  } 
 | 
}; 
 | 
  
 | 
const openScan = () => { 
 | 
  scanRef.value.triggerScan(); 
 | 
}; 
 | 
  
 | 
// 打开手动输入弹框 
 | 
const openManualInput = () => { 
 | 
  // 检查是否已选择标签 
 | 
  if (!tab.value) { 
 | 
    toast.error("请先选择一个层"); 
 | 
    return; 
 | 
  } 
 | 
  showManualInput.value = true; 
 | 
}; 
 | 
  
 | 
// 关闭手动输入弹框 
 | 
const closeManualInput = () => { 
 | 
  showManualInput.value = false; 
 | 
  manualOutPutId.value = ""; 
 | 
}; 
 | 
  
 | 
// 手动输入确认 
 | 
const handleManualConfirm = async () => { 
 | 
  if (!manualOutPutId.value.trim()) { 
 | 
    toast.error("请输入质量追溯号"); 
 | 
    return; 
 | 
  } 
 | 
  
 | 
  try { 
 | 
    const { data } = await TwistApi.selectByMonofilamentNumber({ 
 | 
      monofilamentNumber: manualOutPutId.value.trim(), 
 | 
    }); 
 | 
  
 | 
    // 找到当前选中的层 
 | 
    const currentLayer = nodeList.value.find((node) => node.twistedLayer === tab.value); 
 | 
    if (!currentLayer) { 
 | 
      toast.error("未找到当前选中的层"); 
 | 
      return; 
 | 
    } 
 | 
  
 | 
    // 检查当前层是否已存在该单丝 
 | 
    const exists = currentLayer.strandedWireDish?.some( 
 | 
      (item: any) => item.monofilamentNumber === data.monofilamentNumber 
 | 
    ); 
 | 
  
 | 
    if (!exists) { 
 | 
      const { id, outPutId, wireId, oneLength, ...rest } = data; 
 | 
      const newItem = { 
 | 
        wireId: paramsId.value, 
 | 
        outputId: id, 
 | 
        amount: oneLength, 
 | 
        ongLength: oneLength, 
 | 
        ...rest, 
 | 
      }; 
 | 
  
 | 
      // 添加到当前层的 strandedWireDish 中 
 | 
      if (!currentLayer.strandedWireDish) { 
 | 
        currentLayer.strandedWireDish = []; 
 | 
      } 
 | 
      currentLayer.strandedWireDish.push(newItem); 
 | 
  
 | 
      // 刷新当前层的数据显示 
 | 
      getList(); 
 | 
  
 | 
      // 关闭弹框并清空输入 
 | 
      closeManualInput(); 
 | 
      toast.success("添加成功"); 
 | 
    } else { 
 | 
      toast.error("该单丝已领用,请勿重复添加"); 
 | 
    } 
 | 
  } catch (error: any) { 
 | 
    toast.error(error.msg || "查询失败"); 
 | 
  } 
 | 
}; 
 | 
  
 | 
const getList = async () => { 
 | 
  // 从当前选中层的 strandedWireDish 中获取数据 
 | 
  const currentLayer = nodeList.value.find((node) => node.twistedLayer === tab.value); 
 | 
  if (currentLayer && currentLayer.strandedWireDish) { 
 | 
    pagingRef.value.complete(currentLayer.strandedWireDish); 
 | 
  } else { 
 | 
    pagingRef.value.complete([]); 
 | 
  } 
 | 
}; 
 | 
  
 | 
let nodeList = ref<any[]>([]); 
 | 
// 获取根号 
 | 
const getRootNumber = async (wireId: number) => { 
 | 
  const { code, data, msg } = await TwistApi.getRootNumber({ wireId }); 
 | 
  if (code === 200) { 
 | 
    nodeList.value = data.nodeList; 
 | 
    if (data.otherStrandedWireDish && data.otherStrandedWireDish.length > 0) { 
 | 
      nodeList.value.push({ 
 | 
        strandedWireDish: data.otherStrandedWireDish, 
 | 
        twistedLayer: "其他", 
 | 
        twistId: null, 
 | 
      }); 
 | 
    } 
 | 
    // 设置默认第一层 
 | 
    if (nodeList.value && nodeList.value.length > 0 && !tab.value) { 
 | 
      tab.value = nodeList.value[0].twistedLayer; 
 | 
      console.log("设置默认第一层:", tab.value); 
 | 
      // 设置默认标签后,加载第一层的数据 
 | 
      getList(); 
 | 
    } 
 | 
  } else { 
 | 
    toast.error(msg || "获取根号失败"); 
 | 
  } 
 | 
}; 
 | 
  
 | 
const save = () => { 
 | 
  // 检查 nodeList 中是否有新的单丝数据需要保存 
 | 
  let hasNewData = false; 
 | 
  
 | 
  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; 
 | 
      } 
 | 
    } 
 | 
  }); 
 | 
  
 | 
  if (!hasNewData) { 
 | 
    toast.error("没有新的单丝数据需要保存"); 
 | 
    return; 
 | 
  } 
 | 
  
 | 
  // 显示统计弹框 
 | 
  showStatisticsModal.value = true; 
 | 
}; 
 | 
  
 | 
const handleConfirmSave = async () => { 
 | 
  // 从 nodeList 中收集所有需要保存的新单丝数据 
 | 
  const newData: any[] = []; 
 | 
  
 | 
  nodeList.value.forEach((node) => { 
 | 
    node.strandedWireDish.forEach((item: any) => { 
 | 
      item.saleTwistId = node.twistId; 
 | 
    }); 
 | 
    if (node.strandedWireDish && Array.isArray(node.strandedWireDish)) { 
 | 
      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) 
 | 
    nodeList.value.forEach((node) => { 
 | 
      if (node.strandedWireDish && Array.isArray(node.strandedWireDish)) { 
 | 
        node.strandedWireDish.forEach((item: any) => { 
 | 
          if (item.id === undefined || item.id === null) { 
 | 
            item.id = Date.now(); // 临时标记为已保存 
 | 
          } 
 | 
        }); 
 | 
      } 
 | 
    }); 
 | 
  
 | 
    pagingRef.value.refresh(); 
 | 
    getList(); 
 | 
  } else { 
 | 
    toast.error("保存失败"); 
 | 
  } 
 | 
}; 
 | 
  
 | 
onLoad(async (options: any) => { 
 | 
  // 开启广播监听事件 
 | 
  uni.$on("scanMono", getScanCode); 
 | 
  paramsId.value = options.id; 
 | 
  
 | 
  // 调用获取根号接口 
 | 
  getRootNumber(options.id); 
 | 
  // getRootNumber(118); 
 | 
}); 
 | 
onUnload(() => { 
 | 
  // 开启广播监听事件 
 | 
  uni.$off("scanMono", getScanCode); 
 | 
}); 
 | 
</script> 
 | 
  
 | 
<style lang="scss" scoped> 
 | 
.list_box { 
 | 
  height: calc(100vh - 50px); 
 | 
  background: #f3f9f8; 
 | 
  display: flex; 
 | 
  flex-direction: column; 
 | 
} 
 | 
  
 | 
// 手动输入弹框样式 
 | 
.manual-input-modal { 
 | 
  width: 320px; 
 | 
  background: #fff; 
 | 
  border-radius: 12px; 
 | 
  overflow: hidden; 
 | 
  
 | 
  .modal-header { 
 | 
    display: flex; 
 | 
    justify-content: space-between; 
 | 
    align-items: center; 
 | 
    padding: 16px 20px; 
 | 
    border-bottom: 1px solid #f0f0f0; 
 | 
  
 | 
    .title { 
 | 
      font-size: 18px; 
 | 
      font-weight: 600; 
 | 
      color: #333; 
 | 
    } 
 | 
  } 
 | 
  
 | 
  .modal-content { 
 | 
    padding: 20px; 
 | 
  
 | 
    .input-label { 
 | 
      font-size: 14px; 
 | 
      color: #333; 
 | 
      margin-bottom: 8px; 
 | 
      font-weight: 500; 
 | 
    } 
 | 
  } 
 | 
  
 | 
  .modal-footer { 
 | 
    display: flex; 
 | 
    gap: 12px; 
 | 
    padding: 16px 20px; 
 | 
    border-top: 1px solid #f0f0f0; 
 | 
  } 
 | 
} 
 | 
  
 | 
:deep(.manual-input-modal .confirm-btn) { 
 | 
  background-color: #0d867f !important; 
 | 
  border-color: #0d867f !important; 
 | 
  
 | 
  .wd-button__content { 
 | 
    color: #fff !important; 
 | 
  } 
 | 
} 
 | 
  
 | 
// tab容器样式 
 | 
.tabs-container { 
 | 
  height: calc(100vh - 200px); 
 | 
  display: flex; 
 | 
  flex-direction: column; 
 | 
} 
 | 
  
 | 
.content { 
 | 
  height: calc(100vh - 200px); 
 | 
  width: 100%; 
 | 
} 
 | 
  
 | 
:deep(.wd-button__content) { 
 | 
  color: #0d867f; 
 | 
} 
 | 
: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; 
 | 
} 
 | 
</style> 
 |