绞线报工:二维码领用单丝,一层领完之后就自动切换层(从里到外),PDA:领用时需要选中层数,然后进行领用。PC端需要分层展示各层单丝领用情况。
已添加1个文件
已修改2个文件
457 ■■■■■ 文件已修改
src/api/product/twist.ts 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/production/twist/components/StatisticsModal.vue 262 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/production/twist/receive/monofil.vue 186 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/product/twist.ts
@@ -44,6 +44,15 @@
      data: data,
    });
  },
  // èŽ·å–æ ¹å·
  getRootNumber(params: { wireId: number }) {
    return request<BaseResult<any>>({
      url: "/app/getStrandedWireDishTypeByWire",
      method: "GET",
      data: params,
    });
  },
};
export default TwistApi;
src/pages/production/twist/components/StatisticsModal.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,262 @@
<template>
  <!-- ä½¿ç”¨åŽŸç”Ÿå®žçŽ°æ›¿ä»£ wd-popup -->
  <view
    v-if="visible"
    style="
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background: rgba(0, 0, 0, 0.5);
      z-index: 10000;
    "
  >
    <view
      class="statistics-modal"
      style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%)"
    >
      <view class="modal-header">
        <text class="title">单丝领用统计</text>
        <wd-icon name="close" @click="handleClose" />
      </view>
      <view class="modal-content">
        <view class="summary-section">
          <view class="summary-item">
            <text class="label">总盘数:</text>
            <text class="value">{{ totalCount }} ç›˜</text>
          </view>
          <view class="summary-item">
            <text class="label">总重量:</text>
            <text class="value">{{ totalWeight.toFixed(2) }} kg</text>
          </view>
          <view class="summary-item">
            <text class="label">总长度:</text>
            <text class="value">{{ totalLength.toFixed(2) }} M</text>
          </view>
        </view>
        <view class="layer-section">
          <text class="section-title">各层统计</text>
          <view class="layer-list">
            <view v-for="layer in layerStatistics" :key="layer.twistedLayer" class="layer-item">
              <view class="layer-header">
                <text class="layer-name">{{ layer.twistedLayer }}</text>
                <text class="layer-count">{{ layer.count }} ç›˜</text>
              </view>
              <view class="layer-details">
                <text class="detail-text">重量:{{ layer.weight.toFixed(2) }} kg</text>
                <text class="detail-text">长度:{{ layer.length.toFixed(2) }} M</text>
              </view>
            </view>
          </view>
        </view>
      </view>
      <view class="modal-footer">
        <wd-button @click="handleClose" type="default">取消</wd-button>
        <wd-button type="primary" @click="handleConfirm" custom-class="confirm-btn">
          ç¡®è®¤ä¿å­˜
        </wd-button>
      </view>
    </view>
  </view>
</template>
<script setup lang="ts">
interface LayerStatistic {
  twistedLayer: string;
  count: number;
  weight: number;
  length: number;
}
const props = defineProps<{
  visible: boolean;
  nodeList: any[];
}>();
// ç›‘听 visible å˜åŒ–
watch(
  () => props.visible,
  () => {
    // å¯ä»¥åœ¨è¿™é‡Œæ·»åŠ éœ€è¦çš„é€»è¾‘
  }
);
const emit = defineEmits<{
  "update:visible": [value: boolean];
  confirm: [];
}>();
// è®¡ç®—统计数据
const layerStatistics = computed<LayerStatistic[]>(() => {
  const stats: { [key: string]: LayerStatistic } = {};
  // éåŽ†æ¯å±‚çš„å•ä¸æ•°æ®
  props.nodeList.forEach((node) => {
    const layerName = node.twistedLayer;
    if (!stats[layerName]) {
      stats[layerName] = {
        twistedLayer: layerName,
        count: 0,
        weight: 0,
        length: 0,
      };
    }
    // ç»Ÿè®¡è¯¥å±‚的单丝数据
    if (node.strandedWireDish && Array.isArray(node.strandedWireDish)) {
      node.strandedWireDish.forEach((item: any) => {
        stats[layerName].count++;
        stats[layerName].weight += parseFloat(item.actuallyWeight || 0);
        stats[layerName].length += parseFloat(item.amount || 0);
      });
    }
  });
  return Object.values(stats);
});
// è®¡ç®—总数据
const totalCount = computed(() => {
  return layerStatistics.value.reduce((sum, layer) => sum + layer.count, 0);
});
const totalWeight = computed(() => {
  return layerStatistics.value.reduce((sum, layer) => sum + layer.weight, 0);
});
const totalLength = computed(() => {
  return layerStatistics.value.reduce((sum, layer) => sum + layer.length, 0);
});
const handleClose = () => {
  emit("update:visible", false);
};
const handleConfirm = () => {
  emit("confirm");
  emit("update:visible", false);
};
</script>
<style lang="scss" scoped>
.statistics-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;
}
.summary-section {
  margin-bottom: 20px;
  .summary-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 8px;
    .label {
      font-size: 16px;
      color: #666;
    }
    .value {
      font-size: 16px;
      font-weight: 600;
      color: #0d867f;
    }
  }
}
.layer-section {
  .section-title {
    font-size: 16px;
    font-weight: 600;
    color: #333;
    margin-bottom: 12px;
    display: block;
  }
  .layer-list {
    .layer-item {
      background: #f8f9fa;
      border-radius: 8px;
      padding: 12px;
      margin-bottom: 8px;
      .layer-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 4px;
        .layer-name {
          font-size: 14px;
          font-weight: 500;
          color: #333;
        }
        .layer-count {
          font-size: 14px;
          color: #0d867f;
          font-weight: 600;
        }
      }
      .layer-details {
        .detail-text {
          font-size: 12px;
          color: #666;
        }
      }
    }
  }
}
.modal-footer {
  display: flex;
  gap: 12px;
  padding: 16px 20px;
  border-top: 1px solid #f0f0f0;
  .cancel-btn {
    flex: 1;
  }
  .confirm-btn {
    flex: 1;
  }
}
// ç¡®è®¤æŒ‰é’®æ ·å¼
:deep(.confirm-btn) {
  background-color: #0d867f !important;
  border-color: #0d867f !important;
}
:deep(.confirm-btn .wd-button__content) {
  color: #fff !important;
}
</style>
src/pages/production/twist/receive/monofil.vue
@@ -2,7 +2,6 @@
  <view class="list_box">
    <z-paging
      ref="pagingRef"
      v-model="cardList"
      :fixed="false"
      :auto-show-back-to-top="true"
      :loading-more-enabled="false"
@@ -15,7 +14,16 @@
          </template>
        </CardTitle>
      </template>
      <MonofilCard v-for="(item, index) in cardList" :key="index" :data="item" />
      <!-- <MonofilCard v-for="(item, index) in cardList" :key="index" :data="item" /> -->
      <wd-tabs v-model="tab" slidable="always">
        <block v-for="item in nodeList" :key="item">
          <wd-tab :title="item.twistedLayer" :name="item.twistedLayer">
            <view class="content">
              <MonofilCard v-for="(m, i) in item.strandedWireDish" :key="i" :data="m" />
            </view>
          </wd-tab>
        </block>
      </wd-tabs>
      <template #bottom>
        <view class="flex justify-center items-center">
          <wd-button block @click="save">
@@ -25,6 +33,11 @@
      </template>
    </z-paging>
    <Scan ref="scanRef" emitName="scanMono" />
    <StatisticsModal
      v-model:visible="showStatisticsModal"
      :nodeList="nodeList"
      @confirm="handleConfirmSave"
    />
    <wd-toast />
  </view>
</template>
@@ -32,6 +45,7 @@
<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";
@@ -44,8 +58,17 @@
const paramsId = ref();
const pagingRef = ref();
const scanRef = ref();
const cardList = ref<any[]>([]);
const toast = useToast();
const tab = ref("");
const showStatisticsModal = ref(false);
// ç›‘听标签切换
watch(tab, () => {
  if (tab.value) {
    console.log("tab.value:===========1", tab.value);
    getList();
  }
});
const getScanCode = async (code: any) => {
  console.log("自定义扫描的结果回调函数:", code);
@@ -55,24 +78,43 @@
  const { data } = await TwistApi.getScarn({
    outPutId: JSON.parse(code.code).id,
  });
  const exists = cardList.value.some((item) => item.monofilamentNumber === data.monofilamentNumber);
  // æ£€æŸ¥æ˜¯å¦å·²é€‰æ‹©æ ‡ç­¾
  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;
  }
  // æ£€æŸ¥å½“前层是否已存在该单丝
  const exists = currentLayer.strandedWireDish?.some(
    (item: any) => item.monofilamentNumber === data.monofilamentNumber
  );
  if (!exists) {
    const { id, outPutId, wireId, oneLength, ...rest } = data;
    console.log("sb", {
    const newItem = {
      wireId: paramsId.value,
      outputId: id,
      amount: oneLength,
      ongLength: oneLength,
      ...rest,
    });
    cardList.value.push({
      wireId: paramsId.value,
      outputId: id,
      amount: oneLength,
      ongLength: oneLength,
      ...rest,
    });
    pagingRef.value.complete(cardList.value);
    };
    // æ·»åŠ åˆ°å½“å‰å±‚çš„ strandedWireDish ä¸­
    if (!currentLayer.strandedWireDish) {
      currentLayer.strandedWireDish = [];
    }
    currentLayer.strandedWireDish.push(newItem);
    // åˆ·æ–°å½“前层的数据显示
    getList();
  } else {
    toast.error("该单丝已领用,请勿重复扫码");
  }
@@ -83,22 +125,100 @@
};
const getList = async () => {
  const { code, data } = await ManageApi.getStrandedWireDish({
    wireId: paramsId.value,
    type: "单丝",
  });
  if (code == 200) {
    pagingRef.value.complete(data);
  // ä»Žå½“前选中层的 strandedWireDish ä¸­èŽ·å–æ•°æ®
  const currentLayer = nodeList.value.find((node) => node.twistedLayer === tab.value);
  if (currentLayer && currentLayer.strandedWireDish) {
    pagingRef.value.complete(currentLayer.strandedWireDish);
  } else {
    pagingRef.value.complete([]);
  }
};
const save = async () => {
  const value = cardList.value.filter((item: { id?: number }) => item.id === undefined || item.id === null);
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 { code,msg } = await TwistApi.addStrandedWireDish(value);
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.twistId = 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);
    cardList.value = [];
    // æ¸…空所有层中已保存的数据(给已保存的数据添加 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 {
@@ -106,10 +226,14 @@
  }
};
onLoad((options: any) => {
onLoad(async (options: any) => {
  // å¼€å¯å¹¿æ’­ç›‘听事件
  uni.$on("scanMono", getScanCode);
  paramsId.value = options.id;
  // è°ƒç”¨èŽ·å–æ ¹å·æŽ¥å£
  getRootNumber(options.id);
  // getRootNumber(118);
});
onUnload(() => {
  // å¼€å¯å¹¿æ’­ç›‘听事件
@@ -125,4 +249,16 @@
:deep(.wd-button__content) {
  color: #0d867f;
}
:deep(.zp-paging-container) {
  background: transparent !important;
}
:deep(.zp-paging-container-content) {
  background: transparent !important;
}
:deep(.wd-tabs) {
  background: transparent !important;
}
:deep(.wd-tabs__nav) {
  margin-bottom: 10px;
}
</style>