Explorar o código

解决冲突。

jiaxiaoqiang hai 1 ano
pai
achega
55c79b7b2f

+ 1 - 1
.env.development

@@ -13,7 +13,7 @@ VITE_APP_UPLOAD_URL = 'http://192.168.101.4:9000'
 # 线上接口地址
 # VITE_APP_API_URL = http://vapi.youlai.tech
 # 开发接口地址
- VITE_APP_API_URL = 'http://192.168.101.4:8079'
+ VITE_APP_API_URL = 'http://192.168.101.30:8079'
 
 ``
 # 是否启用 Mock 服务

+ 1 - 1
src/api/prepare/index.ts

@@ -57,7 +57,7 @@ export function vehicleBiding(data: any) {
 //箱子出库
 export function outBox(data: any) {
   return request({
-    url: "/api/v3/wmsOrder/outBox",
+    url: "/api/v1/wmsOrder/outBox",
     method: "post",
     data,
   });

+ 44 - 0
src/api/process/traceability.ts

@@ -0,0 +1,44 @@
+import request from "@/utils/request";
+
+// 通过流转卡号获取信息
+export function getTraceabilityInfo(seq: string) {
+  return request({
+    url: `/api/v1/process/web/traceability/get/${seq}`,
+    method: "get",
+  });
+}
+
+// 通过流转卡号获取标题内容数量
+export function getTabCount(data: any) {
+  return request({
+    url: "/api/v1/process/web/traceability/tabCount",
+    method: "post",
+    data,
+  });
+}
+// 生产履历列表数据分页
+export function getInfo(data: any) {
+  return request({
+    url: "/api/v1/process/info/page",
+    method: "post",
+    data,
+  });
+}
+//已采集物料界面数据分页
+
+export function getMaterialsInfo(data: any) {
+  return request({
+    url: "/api/v1/process/web/traceability/materialsRecordInfo/page",
+    method: "post",
+    data,
+  });
+}
+//记录项数据获取
+
+export function getRecordInfo(data: any) {
+  return request({
+    url: "/api/v1/process/web/traceability/traceabilityRecordInfo/page",
+    method: "post",
+    data,
+  });
+}

+ 53 - 15
src/components/MessageBox/index.vue

@@ -1,13 +1,25 @@
 <template>
   <div v-show="modelValue" class="body">
-    <div class="item" @click="sendMessage">消息记录</div>
+    <div class="headerTittle">消息记录</div>
     <el-scrollbar class="itemScrollbar">
-      <div class="item" v-for="item in 12"></div>
+      <div class="item" v-for="item in 12">
+        <div>
+          <div>time</div>
+          <div>content</div>
+        </div>
+      </div>
     </el-scrollbar>
+    <div class="bottomBtn">
+      <el-button type="primary" class="btn">下一页</el-button>
+      <el-button class="btn" type="primary">上一页</el-button>
+      <el-button type="primary" class="btn">关 闭</el-button>
+    </div>
   </div>
 </template>
 
 <script setup lang="ts">
+import { useDictionaryStore } from "@/store";
+const dictS = useDictionaryStore();
 const porps = defineProps({
   modelValue: {
     type: Boolean,
@@ -15,16 +27,12 @@ const porps = defineProps({
   },
 });
 const messages = ref([]);
+const page = ref(1);
+const emits = defineEmits(["update:modelValue"]);
+//连接地址
 const ws = new WebSocket(
   `ws://192.168.101.4:8079/websocket/${localStorage.getItem("token")}`
 );
-const sendMessage = () => {
-  if (ws.readyState === WebSocket.OPEN) {
-    ws.send("确认啊啊啊啊");
-  } else {
-    console.error("WebSocket is not open");
-  }
-};
 ws.onopen = () => {
   console.log("实时已连接");
 };
@@ -36,29 +44,59 @@ ws.onmessage = (event) => {
 ws.onclose = () => {
   console.log("实时连接断开");
 };
-const emits = defineEmits(["update:modelValue"]);
 </script>
 <style scoped lang="scss">
 .body {
-  width: 260px;
+  width: 300px;
   height: 40vh;
   position: fixed;
   right: 20px;
   top: 80px;
   z-index: 3;
-  background-color: red;
+  background-color: white;
   border-radius: 16px;
   overflow: hidden;
+  padding: 0 20px;
+  border: 1px solid black;
+
+  .headerTittle {
+    font-size: $f24;
+    height: 40px;
+    border-bottom: 1px solid #f1f3f5;
+    margin-bottom: 10px;
+  }
 
   .itemScrollbar {
-    height: calc(100% - 80px);
+    height: calc(100% - 100px);
   }
 
   .item {
     width: 100%;
-    height: 60px;
-    background-color: aqua;
     margin-bottom: 10px;
+    display: flex;
+    align-items: center;
+    padding: 0 10px;
+    background-color: #f1f3f5;
+    border-radius: 16px;
+    justify-content: space-between;
+
+    .operate {
+      margin-left: 10px;
+    }
+  }
+
+  .bottomBtn {
+    display: flex;
+    justify-content: space-evenly;
+    align-items: center;
+    height: 40px;
+    padding: 0 10px;
+    border-top: 1px solid #f1f3f5;
+    margin-top: 10px;
+
+    .btn {
+      font-weight: 500;
+    }
   }
 }
 </style>

+ 9 - 0
src/router/modules/process.ts

@@ -151,5 +151,14 @@ export default {
         back: true,
       },
     },
+    {
+      path: "traceability",
+      component: () => import("@/views/traceability/index.vue"),
+      name: "traceability",
+      meta: {
+        title: "生产履历",
+        back: true,
+      },
+    },
   ],
 };

+ 1 - 0
src/store/modules/dictionary.ts

@@ -11,6 +11,7 @@ export const useDictionaryStore = defineStore("dictionaryStore", () => {
     "work_order_seq_state",
     "accessories_type",
     "danwei_type",
+    "system_message_type",
   ];
   const dicts = ref<{ [key: string]: any[] }>({});
 

+ 3 - 1
src/store/modules/processView.ts

@@ -7,7 +7,9 @@ export const useProcessStore = defineStore(
     const processInfo = ref<any>({});
     //扫码开工返回值
     const scanInfo = ref<any>({});
-    return { odersData, processInfo, scanInfo };
+    //生产履历现使用的流转卡号
+    const useSeqNo = ref<any>("");
+    return { odersData, processInfo, scanInfo, useSeqNo };
   },
   {
     //开启持久化存储

+ 1 - 1
src/typings/components.d.ts

@@ -111,4 +111,4 @@ declare module 'vue' {
 export interface ComponentCustomProperties {
   vLoading: typeof import('element-plus/es')['ElLoadingDirective']
 }
-}
+

+ 9 - 5
src/views/prepare-complete-suit/components/first.vue

@@ -1,7 +1,7 @@
 <template>
   <el-row :gutter="20">
     <el-col :span="5" class="elColClasss">
-      <el-input class="searchInput" style="margin-bottom: 10px" v-model="seachInput" placeholder="搜索计划编号">
+      <el-input class="searchInput" style="margin-bottom: 10px" v-model="seachInput" placeholder="搜索工单编号">
         <template #prefix> </template></el-input>
       <el-scrollbar>
         <Order v-for="(item, index) in seachOrderData" :key="index"
@@ -27,7 +27,9 @@
                 <span :class="scope.row.totalMaterial - scope.row.completeNum < 0
                     ? 'sumOk'
                     : 'sumFail'
-                  ">{{ scope.row.totalMaterial - scope.row.completeNum }}</span>
+                  ">{{
+                    scope.row.totalMaterial - scope.row.completeNum < 1 ? 0 : scope.row.totalMaterial -
+                      scope.row.completeNum }}</span>
               </template>
             </el-table-column>
 
@@ -62,8 +64,8 @@
 <script lang="ts" setup>
 import Order from "./order.vue";
 import Steps from "./steps.vue";
-import ScanCode from "../popUpView/scanCode.vue";
-import ShowInfo from "../popUpView/showInfo.vue";
+import ScanCode from "../firstPopUpView/scanCode.vue";
+import ShowInfo from "../firstPopUpView/showInfo.vue";
 import {
   getStation,
   workOrderPage,
@@ -102,7 +104,9 @@ const showInfoPop = async (row: any) => {
 const seachOrderData = computed(() => {
   if (seachInput.value == "") return orderData.value;
   else {
-    return orderData.value.filter((item) => item.orderCode == seachInput.value);
+    return orderData.value.filter(
+      (item) => item.workOrderCode == seachInput.value
+    );
   }
 });
 const getPagination = (obj: any) => {

src/views/prepare-complete-suit/popUpView/bangding.vue → src/views/prepare-complete-suit/firstPopUpView/bangding.vue


+ 16 - 2
src/views/prepare-complete-suit/popUpView/bindingScan.vue

@@ -19,6 +19,7 @@
             <el-table-column prop="materialCode" label="物料编号" />
             <el-table-column prop="spec" label="规格" />
             <el-table-column prop="num" label="数量" align="center" />
+            <el-table-column prop="batchCode" label="流转卡号/批次号" align="center" />
             <el-table-column prop="" label="操作" align="center">
               <template #default="scope">
                 <el-popconfirm title="确认清空?" @confirm="tableDelete(scope.row.materialCode)" confirm-button-text="确定"
@@ -69,7 +70,7 @@
 
       <div class="bottomBtn">
         <el-button class="leftBtn" @click="handleClose">取消</el-button>
-        <el-button class="rightBtn" @click="handleSubmit" type="primary">绑定</el-button>
+        <el-button class="rightBtn" :disabled="scanItemArray.length<1" @click="handleSubmit" type="primary">绑定</el-button>
       </div>
     </div>
   </div>
@@ -120,11 +121,23 @@ const scanItemArray = computed(() => {
         materialName: item.materialName,
         num: item.num,
         spec: item.spec,
+        batchCode: item.batchCode,
       });
     } else {
       resArray.forEach((res) => {
-        if (res.materialCode == item.materialCode) {
+        if (
+          res.materialCode == item.materialCode &&
+          res.batchCode == item.batchCode
+        ) {
           res.num = Number(res.num) + Number(item.num);
+        } else {
+          resArray.push({
+            materialCode: item.materialCode,
+            materialName: item.materialName,
+            num: item.num,
+            spec: item.spec,
+            batchCode: item.batchCode,
+          });
         }
       });
     }
@@ -155,6 +168,7 @@ const enterfnc = async () => {
     recordArray.value.unshift(obj);
     scanCode.value = "";
     scanAllNum.value = scanAllNum.value + 1;
+    ElMessage.success('扫描成功!')
   }
 };
 const addTableSum = computed((code) => {

src/views/prepare-complete-suit/popUpView/scanCode.vue → src/views/prepare-complete-suit/firstPopUpView/scanCode.vue


+ 46 - 24
src/views/prepare-complete-suit/popUpView/showInfo.vue

@@ -17,10 +17,11 @@
 
               <el-button @click="cancelBingding" type="primary" v-if="bingdingStatus || outboundStatus" plain>取
                 消</el-button>
-              <el-button type="primary" style="background-color: #f9bf5c90" v-if="!bingdingStatus &&
+              <el-button type="primary" style="background-color: #f9bf5c90" v-if="
+                !bingdingStatus &&
                 selectedType == 'no' &&
                 outboundStatus == false
-                " @click="outboundFnc" plain>出 库</el-button>
+              " @click="outboundFnc" plain>出 库</el-button>
               <el-button type="primary" @click="submit" style="background-color: #f9bf5c90; color: white; border: 0px"
                 v-if="bingdingStatus" plain>确 认</el-button>
               <el-button type="primary" @click="submit" style="background-color: #f9bf5c90; color: white; border: 0px"
@@ -36,27 +37,25 @@
                   <div>
                     已装数量:{{
                       selectRowData.completeNum
-                      ? selectRowData.completeNum
-                      : "-"
+                        ? selectRowData.completeNum
+                        : "-"
                     }}
                   </div>
                   <div>所需总数:{{ selectRowData.totalMaterial }}</div>
                   <div>
                     还需数量:{{
                       selectRowData.totalMaterial -
-                      selectRowData.completeNum +
-                      topSum
-                    }}
+                        selectRowData.completeNum -
+                        topSum < 1 ? 0 : selectRowData.totalMaterial - selectRowData.completeNum - topSum }} </div>
+                  </div>
+                  <div class="selectInfoItem" v-if="selectedType == 'yes'" @click="closeTopItem(item.selectedIndex)"
+                    v-for="item in setTopItem">
+                    <div>料箱名称:</div>
+                    <div>{{ item.name }}</div>
+                    <div>料箱编号:</div>
+                    <div>{{ item.code }}</div>
                   </div>
                 </div>
-                <div class="selectInfoItem" v-if="selectedType == 'yes'" @click="closeTopItem(item.selectedIndex)"
-                  v-for="item in setTopItem">
-                  <div>料箱名称:</div>
-                  <div>{{ item.name }}</div>
-                  <div>料箱编号:</div>
-                  <div>{{ item.code }}</div>
-                </div>
-              </div>
             </el-scrollbar>
           </div>
           <el-scrollbar class="scrollbar">
@@ -68,7 +67,10 @@
                     : item.isEnable == 2
                       ? 'item noBound'
                       : 'item'
-                " v-if="itemShowStatus(item)" @click="setSelectIndex(index)">
+                " :style="index == selectIndex
+                    ? 'border: 3px solid #6cc2ff;box-shadow: 5px #6cc2ff;'
+                    : ''
+                  " v-if="itemShowStatus(item)" @click="setSelectIndex(index)">
                 <div>料箱名称:</div>
                 <div>{{ item.name }}</div>
                 <div>料箱编号:</div>
@@ -143,13 +145,14 @@ const itemShowStatus = (item: any) => {
 };
 const setSelectedType = (type: string) => {
   selectedType.value = type;
+  selectIndex.value = null;
 };
 const outboundFnc = () => {
   outboundStatus.value = true;
   disabled.value = true;
 };
 const selectIndexInfoData = computed(() => {
-  if (materialData.value.length > 0) {
+  if (materialData.value.length > 0 && selectIndex.value) {
     return materialData.value[selectIndex.value].list;
   } else {
     return [];
@@ -159,6 +162,15 @@ const selectIndexInfoData = computed(() => {
 const setSelectIndex = (index: number) => {
   selectIndex.value = index;
   if (selectedType.value == "yes") {
+    //先判定是否现在数量已经够了
+    if (
+      selectRowData.value.totalMaterial -
+      selectRowData.value.completeNum -
+      topSum.value <
+      1 &&
+      bingdingStatus.value
+    )
+      return ElMessage.warning("现数目已达需要值,请不要过量绑定!");
     //在符合的条件下
     if (bingdingStatus.value) {
       if (materialData.value[selectIndex.value].selected == true) {
@@ -188,8 +200,8 @@ const setTopItem = computed(() => {
 const topSum = computed(() => {
   let sum = 0;
   const array = materialData.value.filter((item) => item.selected == true);
-  for (let i = 0; i++; i < array.length) {
-    sum = array[i].xxxsum;
+  for (let i = 0; i < array.length; i++) {
+    sum = sum + array[i].num;
   }
   return sum;
 });
@@ -206,11 +218,21 @@ const cancelBingding = () => {
   outboundStatus.value = false;
   disabled.value = false;
 };
+//确认操作
 const submit = () => {
+  if (bingdingStatus.value == true) {
+    if (setTopItem.value.length > 0) {
+      bindingTitle.value = "绑定确认";
+    } else {
+      return ElMessage.warning("绑定载具数量不能为0!");
+    }
+  }
   if (outboundStatus.value == true) {
-    bindingTitle.value = "确认出库";
-  } else {
-    bindingTitle.value = "绑定确认";
+    if (outboundIndex.value != null) {
+      bindingTitle.value = "确认出库";
+    } else {
+      return ElMessage.warning("请选择出库载具!");
+    }
   }
   showStatus.value = true;
 };
@@ -248,9 +270,9 @@ const submitData = async () => {
     if (code == "200") {
       ElMessage.success("出库成功!");
       //页面数据删除
-
       materialData.value.splice(outboundIndex.value, 1);
       outboundIndex.value = null;
+      showStatus.value = false;
     }
   }
 };
@@ -387,7 +409,7 @@ const submitData = async () => {
       margin: $p20;
       padding: $p20;
       cursor: pointer;
-      box-sizing: border-box;
+      box-sizing: border-box !important;
     }
   }
 }

+ 2 - 2
src/views/prepare-complete-suit/index.vue

@@ -22,7 +22,6 @@
         </div>
       </el-tab-pane>
     </el-tabs>
-    <ShowInfo />
   </div>
 </template>
 
@@ -33,9 +32,10 @@ import Third from "./components/third.vue";
 import ShowInfo from "./popUpView/showInfo.vue";
 import { TabsPaneContext } from "element-plus";
 
+import ShowInfo from "./firstPopUpView/showInfo.vue";
 const activeName = ref("first");
 const handleClick = (tab: TabsPaneContext, event: Event) => {
-  console.log(tab, event);
+
 };
 </script>
 

+ 6 - 22
src/views/pro-steps/components/wuliaocaiji.vue

@@ -4,21 +4,13 @@
   </div>
   <div class="showCodeBody" v-if="opCompentDataList.length < 1">
     <div class="codeBox">
-      <img
-        src="@/assets/icons/shaoma.svg"
-        style="width: 134px; height: 134px"
-      />
+      <img src="@/assets/icons/shaoma.svg" style="width: 134px; height: 134px" />
       <div class="codeText">扫码物料码添加物料</div>
     </div>
   </div>
   <div class="materialInfoBody" v-else>
-    <div
-      :class="
-        item.needNum - item.realNum == 0 ? 'infoMsg infoMsgImg' : 'infoMsg'
-      "
-      v-for="item in opCompentDataList"
-      @click="toXQPop(item)"
-    >
+    <div :class="item.needNum - item.realNum == 0 ? 'infoMsg infoMsgImg' : 'infoMsg'
+      " v-for="item in opCompentDataList" @click="toXQPop(item)">
       <div class="leftMsg">
         <div class="nameMsg">{{ item.itemName }}</div>
         <div class="describe">{{ item.itemModel }}</div>
@@ -31,17 +23,8 @@
       <svg-icon icon-class="jiaobiao" size="25" class="svgStyle" />
     </div>
   </div>
-  <xiangqingPopUp
-    v-model="showXQ"
-    :showInfoData="showInfoData"
-    :showInfo="showInfo"
-  />
-  <caijiRightPopUp
-    v-model="showCJ"
-    @submit="submit"
-    ref="caijiRef"
-    :seqNo="scanCode"
-  />
+  <xiangqingPopUp v-model="showXQ" :showInfoData="showInfoData" :showInfo="showInfo" />
+  <caijiRightPopUp v-model="showCJ" @submit="submit" ref="caijiRef" :seqNo="scanCode" />
 </template>
 
 <script lang="ts" setup>
@@ -80,6 +63,7 @@ const enterfnc = async () => {
   if (code == "200") {
     scanData.value = data;
     showCJ.value = true;
+    scanCode.value = "";
   }
 };
 const opCompentDataList = ref([]);

+ 16 - 10
src/views/process/components/operate.vue

@@ -7,11 +7,19 @@
         <span class="btnText">叫料</span>
       </el-button>
     </div>
-    <div v-for="(item, index) in operationObjs" :key="index" class="operateBox" @click="handleClick(item)">
-      <span class="operateText">{{ item.text }}</span>
-      <svg-icon v-if="item.icon" :icon-class="item.icon" size="30" />
-      <span v-else>{{ item.num }}</span>
-    </div>
+    <template v-for="(item, index) in operationObjs" :key="index">
+      <div v-if="index == 1
+          ? selectSeqArray.length > 0 && selectSeqIndex > -1
+            ? true
+            : false
+          : true
+        " class="operateBox" @click="handleClick(item)">
+        <span class="operateText">{{ item.text }}</span>
+        <svg-icon v-if="item.icon" :icon-class="item.icon" size="30" />
+        <span v-else>{{ item.num }}</span>
+      </div>
+    </template>
+
     <OperatePop v-model="callStatus" @opeatecall="opeateCall" />
     <CallMaterialsPop v-model="callBoxStatus" />
   </div>
@@ -27,16 +35,13 @@ const operationObjs: { icon?: string; text: string; num?: number }[] = [
     icon: "liuzhuan",
     text: "物料流转",
   },
-  // {
-  //   text: "取暂存料",
-  //   num: 20,
-  // },
   {
     icon: "shengchanlvli",
     text: "生产履历",
   },
 ];
-
+const selectSeqArray = inject("selectSeqArray");
+const selectSeqIndex = inject("selectSeqIndex");
 const handleClick = (item: { text: string }) => {
   switch (item.text) {
     case "物料流转":
@@ -45,6 +50,7 @@ const handleClick = (item: { text: string }) => {
     case "取暂存料":
       break;
     case "生产履历":
+      router.push({ name: "traceability" });
       break;
     default:
       break;

+ 1 - 1
src/views/process/components/scanCode.vue

@@ -16,7 +16,7 @@ const store = useProcessStore();
 const router = useRouter();
 const inputValue = ref("");
 const toProSteps = () => {
-  if (inputValue.value == "") return ElMessage.error("二维码不能为空!");
+  if (inputValue.value == "") return ElMessage.error("不能输入空值!");
   store.odersData.qrCode = inputValue.value;
   getScanData();
 };

+ 7 - 3
src/views/process/components/transferNum.vue

@@ -3,13 +3,11 @@
   <div class="body">
     <el-scrollbar class="scrollbar">
       <Empty v-if="selectSeqArray.length < 1" />
-
       <div class="row" @click="clickCardNum(index)" v-for="(item, index) in selectSeqArray" :key="index">
-        <el-tooltip effect="dark" :content="item.seqNo" placement="right" trigger="click">
+        <el-tooltip effect="dark" :content="item.seqNo" placement="left" trigger="hover">
           <span :class="index == selectSeqIndex ? 'describeText active' : 'describeText'
             " style="cursor: pointer">{{ item.seqNo }}</span>
         </el-tooltip>
-
         <div class="status">
           {{
             dictS.getLableByValue("work_order_seq_state", String(item.state))
@@ -22,12 +20,18 @@
 
 <script lang="ts" setup>
 import { useDictionaryStore } from "@/store";
+import { useProcessStore } from "@/store";
+const store = useProcessStore();
 const dictS = useDictionaryStore();
 const selectSeqIndex = inject("selectSeqIndex");
 const selectSeqArray = inject("selectSeqArray");
 const clickCardNum = (index: number) => {
   selectSeqIndex.value = index;
+  store.useSeqNo = selectSeqArray.value[selectSeqIndex.value].seqNo;
 };
+onMounted(() => {
+  if (!selectSeqIndex.value) store.useSeqNo = "";
+});
 </script>
 
 <style lang="scss" scoped>

+ 2 - 1
src/views/process/main.vue

@@ -20,6 +20,7 @@ import Orders from "@/views/process/orders.vue";
 import Processes from "@/views/process/processes.vue";
 import CurrentProduction from "@/views/process/currentProduction.vue";
 import { getOrders } from "@/api/process";
+
 defineOptions({ name: "ProcessMain" });
 //未完成订单数组
 const ordersDataArray = ref([]);
@@ -30,7 +31,7 @@ const selectOrderIndex = ref(NaN);
 // 获取选中订单对应流转卡号的Data
 const selectSeqArray = ref([]);
 // 获取选中订单对应流转卡号的index
-const selectSeqIndex = ref(0);
+const selectSeqIndex = ref(null);
 
 const setSelectOrderIndex = (value: number) => {
   selectOrderIndex.value = value;

+ 11 - 0
src/views/traceability/components/check.vue

@@ -0,0 +1,11 @@
+<template>
+  <div>1</div>
+</template>
+
+<script lang="ts" setup>
+onMounted(() => {
+  console.log("f1");
+});
+</script>
+
+<style lang="scss" scoped></style>

+ 11 - 0
src/views/traceability/components/equit.vue

@@ -0,0 +1,11 @@
+<template>
+  <div>1</div>
+</template>
+
+<script lang="ts" setup>
+onMounted(() => {
+  console.log("f1");
+});
+</script>
+
+<style lang="scss" scoped></style>

+ 11 - 0
src/views/traceability/components/fault.vue

@@ -0,0 +1,11 @@
+<template>
+  <div>1</div>
+</template>
+
+<script lang="ts" setup>
+onMounted(() => {
+  console.log("f1");
+});
+</script>
+
+<style lang="scss" scoped></style>

+ 62 - 0
src/views/traceability/components/materials.vue

@@ -0,0 +1,62 @@
+<template>
+  <div class="collapseStyle">
+    <el-scrollbar style="border: 1px solid #ebeef5" :height="tableHeight">
+      <el-collapse accordion>
+        <el-collapse-item v-for="(item, index) in materialsData" :key="index" :title="item.opName" :name="index">
+          <el-table :data="item.children" style="margin: 10px" border>
+            <el-table-column prop="itemName" label="物料名称" />
+            <el-table-column prop="itemModel" label="物料规格" />
+            <el-table-column prop="itemCode" label="物料编号" />
+            <el-table-column prop="needNum" label="需求数量" />
+            <el-table-column prop="realNum" label="已采集数量" />
+          </el-table>
+        </el-collapse-item>
+      </el-collapse>
+    </el-scrollbar>
+    <Pagination position="right" :page="page" :limit="limit" :total="total" @pagination="getPagination" />
+  </div>
+</template>
+
+<script lang="ts" setup>
+import { useProcessStore } from "@/store";
+import { getMaterialsInfo } from "@/api/process/traceability";
+const store = useProcessStore();
+const page = ref(1);
+const limit = ref(10);
+const total = ref(10);
+const materialsData = ref([]);
+const tableHeight = ref(null);
+const getPagination = async () => {
+  const { data } = await getMaterialsInfo({
+    pageNo: page.value,
+    pageSize: limit.value,
+    seqNo: store.useSeqNo,
+  });
+  total.value = data.totalCount;
+  materialsData.value = data.records;
+  // materialsData.value.push(data.records[0]);
+  // materialsData.value.push(data.records[0]);
+  // materialsData.value.push(data.records[0]);
+  // materialsData.value.push(data.records[0]);
+  // materialsData.value.push(data.records[0]);
+  // materialsData.value.push(data.records[0]);
+  // materialsData.value.push(data.records[0]);
+  // materialsData.value.push(data.records[0]);
+  // materialsData.value.push(data.records[0]);
+  // materialsData.value.push(data.records[0]);
+  // materialsData.value.push(data.records[0]);
+};
+//动态控制高度
+const setTableHeight = () => {
+  tableHeight.value =
+    Number(document.getElementById("tabBox").offsetHeight) - 70;
+};
+onMounted(() => {
+  getPagination();
+  setTableHeight();
+});
+</script>
+
+<style lang="scss" scoped>
+.collapseStyle {}
+</style>

+ 34 - 0
src/views/traceability/components/record.vue

@@ -0,0 +1,34 @@
+<template>
+  <div class="collapseStyle"></div>
+</template>
+
+<script lang="ts" setup>
+import { useProcessStore } from "@/store";
+import { getMaterialsInfo } from "@/api/process/traceability";
+const store = useProcessStore();
+const page = ref(1);
+const limit = ref(10);
+const total = ref(10);
+const materialsData = ref([]);
+const tableHeight = ref(null);
+const getPagination = async () => {
+  const { data } = await getMaterialsInfo({
+    pageNo: page.value,
+    pageSize: limit.value,
+    seqNo: store.useSeqNo,
+  });
+  total.value = data.totalCount;
+  materialsData.value = data.records;
+};
+//动态控制高度
+const setTableHeight = () => {
+  tableHeight.value =
+    Number(document.getElementById("tabBox").offsetHeight) - 70;
+};
+onMounted(() => {
+  getPagination();
+  setTableHeight();
+});
+</script>
+
+<style lang="scss" scoped></style>

+ 50 - 0
src/views/traceability/components/traceability.vue

@@ -0,0 +1,50 @@
+<template>
+  <el-table :data="tableData" id="tableStyle" :height="tableHeight" border>
+    <el-table-column prop="operationName" label="工序名称" />
+    <el-table-column prop="workSection" label="工段" />
+    <el-table-column prop="currentState" label="状态" />
+    <el-table-column prop="realStartWhen" label="开始时间" />
+    <el-table-column prop="realEndWhen" label="结束时间" />
+    <el-table-column prop="creator" label="操作人" />
+    <el-table-column prop="standardWorktime" label="工时" />
+    <el-table-column prop="operationSort" label="工步" />
+  </el-table>
+  <Pagination position="right" :page="page" :limit="limit" :total="total" @pagination="getPagination" />
+</template>
+
+<script lang="ts" setup>
+import { useProcessStore } from "@/store";
+import { getInfo } from "@/api/process/traceability";
+const store = useProcessStore();
+const page = ref(1);
+const limit = ref(10);
+const total = ref(10);
+const tableData = ref([]);
+const tableHeight = ref(null);
+//动态控制表格高度
+const setTableHeight = () => {
+  tableHeight.value =
+    Number(document.getElementById("tabBox").offsetHeight) - 60;
+};
+const getPagination = async () => {
+  const { data } = await getInfo({
+    pageNo: page.value,
+    pageSize: limit.value,
+    seqNo: store.useSeqNo,
+  });
+  total.value = data.totalCount;
+  tableData.value = data.records;
+  tableData.value.push(data.records[0]);
+  tableData.value.push(data.records[0]);
+  tableData.value.push(data.records[0]);
+  tableData.value.push(data.records[0]);
+  tableData.value.push(data.records[0]);
+  tableData.value.push(data.records[0]);
+};
+onMounted(() => {
+  getPagination();
+  setTableHeight();
+});
+</script>
+
+<style lang="scss" scoped></style>

+ 205 - 2
src/views/traceability/index.vue

@@ -1,9 +1,212 @@
 <template>
-  <div class="mainContentBox">生产履!</div>
+  <div class="mainContentBox">
+    <!-- 基础信息展示 -->
+    <div class="contentBody">
+      <div class="headerInfo">
+        <el-descriptions class="descriptions" :column="3" border>
+          <el-descriptions-item>
+            <template #label>
+              <div class="cell-item">
+                <el-icon>
+                  <user />
+                </el-icon>
+                产品名称
+              </div>
+            </template>
+            kooriookami
+          </el-descriptions-item>
+          <el-descriptions-item>
+            <template #label>
+              <div class="cell-item">
+                <el-icon>
+                  <iphone />
+                </el-icon>
+                流转卡号
+              </div>
+            </template>
+            18100000000
+          </el-descriptions-item>
+          <el-descriptions-item>
+            <template #label>
+              <div class="cell-item">
+                <el-icon>
+                  <location />
+                </el-icon>
+                物料编号
+              </div>
+            </template>
+            Suzhou
+          </el-descriptions-item>
+          <el-descriptions-item>
+            <template #label>
+              <div class="cell-item">
+                <el-icon>
+                  <tickets />
+                </el-icon>
+                产品规格
+              </div>
+            </template>
+            <el-tag size="small">School</el-tag>
+          </el-descriptions-item>
+          <el-descriptions-item>
+            <template #label>
+              <div class="cell-item">
+                <el-icon>
+                  <tickets />
+                </el-icon>
+                铭牌号
+              </div>
+            </template>
+            <el-tag size="small">School</el-tag>
+          </el-descriptions-item>
+          <el-descriptions-item>
+            <template #label>
+              <div class="cell-item">
+                <el-icon>
+                  <tickets />
+                </el-icon>
+                Remarks
+              </div>
+            </template>
+            <el-tag size="small">School</el-tag>
+          </el-descriptions-item>
+          <el-descriptions-item>
+            <template #label>
+              <div class="cell-item">
+                <el-icon>
+                  <tickets />
+                </el-icon>
+                工单出站
+              </div>
+            </template>
+            <el-tag size="small">School</el-tag>
+          </el-descriptions-item>
+          <el-descriptions-item>
+            <template #label>
+              <div class="cell-item">
+                <el-icon>
+                  <tickets />
+                </el-icon>
+                交付日期
+              </div>
+            </template>
+            <el-tag size="small">School</el-tag>
+          </el-descriptions-item>
+        </el-descriptions>
+      </div>
+      <div class="tabBox" id="tabBox">
+        <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
+          <el-tab-pane name="f1">
+            <template #label>
+              <el-badge :value="tabCountData.traceability"
+                :type="activeName == 'f1' ? 'warning' : 'primary'">生产履历</el-badge>
+            </template>
+            <Traceability />
+          </el-tab-pane>
+          <el-tab-pane name="f2">
+            <template #label>
+              <el-badge :value="tabCountData.materials"
+                :type="activeName == 'f2' ? 'warning' : 'primary'">已采物料</el-badge>
+            </template>
+            <keep-alive>
+              <template>
+                <Materials v-if="activeName == 'f2'" />
+              </template>
+            </keep-alive>
+          </el-tab-pane>
+          <el-tab-pane name="f3">
+            <template #label>
+              <el-badge :value="tabCountData.record" :type="activeName == 'f3' ? 'warning' : 'primary'">记录项</el-badge>
+            </template>
+            <keep-alive>
+              <template v-if="activeName == 'f3'">
+                <Record />
+              </template> </keep-alive></el-tab-pane>
+          <el-tab-pane name="f4">
+            <template #label>
+              <el-badge :value="tabCountData.check" :type="activeName == 'f4' ? 'warning' : 'primary'">点检判定</el-badge>
+            </template>
+            Config</el-tab-pane>
+          <el-tab-pane name="f5">
+            <template #label>
+              <el-badge :value="tabCountData.equit" :type="activeName == 'f5' ? 'warning' : 'danger'">设备使用</el-badge>
+            </template>
+            Config</el-tab-pane>
+          <el-tab-pane name="f6">
+            <template #label>
+              <el-badge :value="tabCountData.fault" :type="activeName == 'f6' ? 'warning' : 'danger'">报故记录</el-badge>
+            </template>
+            Config</el-tab-pane>
+          <el-tab-pane name="f7">
+            <template #label>
+              <el-badge :value="12" :type="activeName == 'f7' ? 'warning' : 'danger'">缺陷项</el-badge>
+            </template>
+            Config</el-tab-pane>
+        </el-tabs>
+      </div>
+    </div>
+  </div>
 </template>
 
-<script lang="ts" setup></script>
+<script lang="ts" setup>
+import { useProcessStore } from "@/store";
+import { getTraceabilityInfo, getTabCount } from "@/api/process/traceability";
+import Traceability from "./components/traceability.vue";
+// import Materials from "./components/materials.vue";
+const Materials = defineAsyncComponent(
+  () => import("./components/materials.vue")
+);
+const Record = defineAsyncComponent(() => import("./components/record.vue"));
+const store = useProcessStore();
+const router = useRouter();
+const activeName = ref("f1");
+const handleClick = () => { };
+const infoData = ref({});
+const tabCountData = ref({});
+//获取卡号基础信息
+const getInfo = async (seq) => {
+  const { data } = await getTraceabilityInfo(seq);
+  infoData.value = data;
+};
+const getTabCountData = async (seq) => {
+  const { data } = await getTabCount({
+    seqNo: seq,
+  });
+  tabCountData.value = data;
+};
+onMounted(() => {
+  if (!store.useSeqNo) {
+    ElMessage.error("流转卡号有误,请检查");
+    router.go(-1);
+  } else {
+    getInfo(store.useSeqNo);
+    getTabCountData(store.useSeqNo);
+  }
+});
+</script>
 
 <style lang="scss" scoped>
+.mainContentBox {
+  padding: 20px 10%;
+  padding-top: 0;
 
+  .contentBody {
+    padding: 20px;
+    background-color: white;
+    border-radius: 16px;
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+
+    .headerInfo {
+      width: 100%;
+      height: 130px;
+    }
+
+    .tabBox {
+      height: calc(100% - 160px);
+      width: 100%;
+    }
+  }
+}
 </style>