Browse Source

feature/消息记录&&弹窗界面&&首页bug修复

dy 11 months ago
parent
commit
bfca751300

+ 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.30:8079'
+ VITE_APP_API_URL = 'http://192.168.101.4:8079'
 
 ``
 # 是否启用 Mock 服务

+ 2 - 6
src/App.vue

@@ -1,12 +1,8 @@
 <template>
   <el-config-provider :locale="locale" :size="size">
     <!-- 开启水印 -->
-    <el-watermark
-      v-if="watermarkEnabled"
-      :font="{ color: fontColor }"
-      :content="defaultSettings.watermarkContent"
-      class="wh-full"
-    >
+    <el-watermark v-if="watermarkEnabled" :font="{ color: fontColor }" :content="defaultSettings.watermarkContent"
+      class="wh-full">
       <router-view />
     </el-watermark>
     <!-- 关闭水印 -->

+ 8 - 0
src/api/process/index.ts

@@ -28,3 +28,11 @@ export function getScan(data: any) {
     data: data,
   });
 }
+// 流程叫料
+export function callItems(data: any) {
+  return request({
+    url: "/api/v1/process/vehicleOperation/callItems",
+    method: "post",
+    data: data,
+  });
+}

+ 9 - 0
src/api/user/index.ts

@@ -138,3 +138,12 @@ export function importUser(deptId: number, file: File) {
     },
   });
 }
+
+//人员消息分页查询
+export function userMessage(data: any) {
+  return request({
+    url: "/api/v1/sys/message/userMessage",
+    method: "post",
+    data,
+  });
+}

+ 50 - 20
src/components/MessageBox/index.vue

@@ -1,26 +1,33 @@
 <template>
-  <div v-show="modelValue" class="body">
+  <div v-if="modelValue" class="body">
     <div class="headerTittle">消息记录</div>
     <el-scrollbar class="itemScrollbar">
-      <div class="item" v-for="item in 12">
+      <div class="item" v-for="(item, index) in msgData" :key="index">
         <div>
-          <div>time</div>
-          <div>content</div>
+          <div>{{ item.created }}</div>
+          <div>{{ item.title }}</div>
+          <div>
+            {{ item.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>
+      <el-button type="primary" :disabled="setNextStatus" @click="setPage(1)" class="btn">下一页</el-button>
+      <el-button class="btn" :disabled="page == 1" type="primary" @click="setPage(-1)">
+        上一页
+      </el-button>
+
+      <el-button type="primary" class="btn" @click="emits('update:modelValue', false)">关 闭</el-button>
     </div>
   </div>
 </template>
 
 <script setup lang="ts">
 import { useDictionaryStore } from "@/store";
+import { userMessage } from "@/api/user";
 const dictS = useDictionaryStore();
-const porps = defineProps({
+const props = defineProps({
   modelValue: {
     type: Boolean,
     default: false,
@@ -28,22 +35,45 @@ const porps = defineProps({
 });
 const messages = ref([]);
 const page = ref(1);
+const pageSize = ref(5);
+const msgData = ref([]);
+const totalCount = ref(0);
 const emits = defineEmits(["update:modelValue"]);
-//连接地址
-const ws = new WebSocket(
-  `ws://192.168.101.4:8079/websocket/${localStorage.getItem("token")}`
-);
-ws.onopen = () => {
-  console.log("实时已连接");
+const getPageInfo = async () => {
+  const { data, code } = await userMessage({
+    pageNo: page.value,
+    pageSize: pageSize.value,
+  });
+  if (code == "200") {
+    msgData.value = data.records;
+    totalCount.value = data.totalCount;
+  }
 };
-ws.onmessage = (event) => {
-  const receivedMessage = event.data;
-  console.log("Received message:", receivedMessage);
-  messages.value.push(receivedMessage);
+const setNextStatus = computed(() => {
+  return totalCount.value - page.value * pageSize.value > 0 ? false : true;
+});
+const setPage = (num: number) => {
+  page.value = page.value + num;
+  getPageInfo();
 };
-ws.onclose = () => {
-  console.log("实时连接断开");
+const reset = () => {
+  page.value = 0;
+  msgData.value = [];
+  totalCount.value = 0;
 };
+onMounted(() => {
+  getPageInfo();
+});
+watch(
+  () => props.modelValue,
+  (Val) => {
+    if (Val == true) {
+      getPageInfo();
+    } else {
+      reset();
+    }
+  }
+);
 </script>
 <style scoped lang="scss">
 .body {

+ 140 - 0
src/components/RealTimeMsg/index.vue

@@ -0,0 +1,140 @@
+<template>
+  <div class="body">
+    <div :class="showStatus ? 'content noneContent' : 'content haveContnet'">
+      <div class="headerTittle titleText">通知确认</div>
+      <el-scrollbar class="itemScrollbar">
+        <div class="item" v-for="(item, index) in messages" :key="index">
+          <div class="itemContent">
+            <div>{{ item.created }}</div>
+            <div>{{ item.title }}</div>
+            <div>{{ item.content }}</div>
+          </div>
+          <div class="btns">
+            <el-button type="primary" class="btn">收到</el-button>
+          </div>
+        </div>
+        <div class="describeText">
+          {{ messages.length < 1 ? "暂无数据" : "已到最底端~~~" }} </div>
+      </el-scrollbar>
+    </div>
+    <div class="iconBox">
+      <el-icon class="icon" :size="40" @click="showStatus = !showStatus">
+        <Expand v-if="showStatus" />
+        <Fold v-else />
+      </el-icon>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { useDictionaryStore } from "@/store";
+const dictS = useDictionaryStore();
+const porps = defineProps({
+  modelValue: {
+    type: Boolean,
+    default: false,
+  },
+});
+//true关闭 false打开
+const showStatus = ref(true);
+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")}`
+);
+ws.onopen = () => {
+  console.log("实时已连接");
+};
+ws.onmessage = (event) => {
+  const receivedMessage = event.data;
+  messages.value = JSON.parse(receivedMessage).content;
+  if (messages.value.length > 0) {
+    showStatus.value = false;
+  } else {
+    showStatus.value = true;
+  }
+};
+ws.onclose = () => {
+  console.log("实时连接断开");
+};
+</script>
+<style scoped lang="scss">
+.body {
+  position: fixed;
+  height: 100vh;
+  left: 0;
+  display: flex;
+  justify-content: space-between;
+  z-index: 11;
+  top: 0;
+  transition: 0.5s;
+
+  .content {
+    height: 100%;
+    background-color: white;
+    overflow: hidden;
+
+    .headerTittle {
+      height: 40px;
+      text-align: center;
+      border-bottom: 1px solid #f1f3f5;
+    }
+
+    .itemScrollbar {
+      height: calc(100vh - 40px);
+      padding: 20px;
+
+      .confirm {
+        border: 2px solid #00800070 !important;
+      }
+
+      .item {
+        border: 2px solid #ff000070;
+        border-radius: 16px;
+        width: 100%;
+        min-height: 80px;
+        display: flex;
+        justify-content: space-between;
+        padding: 20px;
+        margin-bottom: 20px;
+
+        .itemContent {
+          height: 100%;
+          border: 2px solid #ff000070;
+          border-radius: 16px;
+          padding: 20px;
+        }
+
+        .btns {
+          width: 40px;
+          @include flex;
+          height: 100%;
+          margin-left: 20px;
+        }
+      }
+    }
+  }
+
+  .noneContent {
+    width: 0vw;
+    transition: width 0.5s;
+  }
+
+  .haveContnet {
+    width: 30vw;
+    transition: width 0.5s;
+  }
+
+  .iconBox {
+    width: 20px;
+    height: 100%;
+    @include flex;
+
+    .icon {
+      cursor: pointer;
+    }
+  }
+}
+</style>

+ 13 - 13
src/layout/components/header.vue

@@ -171,19 +171,19 @@ const handleCommand = (command: string | number | object) => {
     margin-right: 10px;
   }
 
-  .activeNotice {
-    animation: swing 0.15s infinite alternate ease-in-out;
-  }
-
-  @keyframes swing {
-    0% {
-      transform: rotate(-45deg);
-    }
-
-    100% {
-      transform: rotate(45deg);
-    }
-  }
+  // .activeNotice {
+  //   animation: swing 0.15s infinite alternate ease-in-out;
+  // }
+
+  // @keyframes swing {
+  //   0% {
+  //     transform: rotate(-45deg);
+  //   }
+
+  //   100% {
+  //     transform: rotate(45deg);
+  //   }
+  // }
 
   .process {
     font-weight: 500;

+ 3 - 4
src/layout/index.vue

@@ -4,10 +4,7 @@
     <section class="app-main">
       <router-view>
         <template #default="{ Component, route }">
-          <transition
-            enter-active-class="animate__animated animate__fadeIn"
-            mode="out-in"
-          >
+          <transition enter-active-class="animate__animated animate__fadeIn" mode="out-in">
             <!--            <keep-alive exclude="ProSteps,AppointOut">-->
             <component :is="Component" />
             <!--            </keep-alive>-->
@@ -15,6 +12,8 @@
         </template>
       </router-view>
     </section>
+    <!-- 左侧消息弹框 -->
+    <RealTimeMsg />
   </div>
 </template>
 

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

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

+ 2 - 0
src/utils/common.ts

@@ -4,6 +4,8 @@ const emitter = mitt();
 
 enum EventsNames {
   APPOINT_OUT = "APPOINT_OUT",
+  //获取当前工序状态 实现叫料按钮的disabled实时效果
+  PROCESS_STEPOBJ = "PROCESS_STEPOBJ",
 }
 
 export { emitter, EventsNames };

+ 2 - 2
src/views/prepare-complete-suit/firstPopUpView/showInfo.vue

@@ -127,7 +127,7 @@ const bindingTitle = ref("");
 const submitType = ref(null);
 const bingdingStatus = ref(false);
 const outboundStatus = ref(false);
-const selectIndex = ref(0);
+const selectIndex = ref(null);
 const itemShowStatus = (item: any) => {
   if (selectedType.value == "yes") {
     if (item.isEnable == 1) {
@@ -152,7 +152,7 @@ const outboundFnc = () => {
   disabled.value = true;
 };
 const selectIndexInfoData = computed(() => {
-  if (materialData.value.length > 0 && selectIndex.value) {
+  if (materialData.value.length > 0 && selectIndex.value!=null) {
     return materialData.value[selectIndex.value].list;
   } else {
     return [];

+ 1 - 7
src/views/process/components/operate.vue

@@ -20,8 +20,7 @@
       </div>
     </template>
 
-    <OperatePop v-model="callStatus" @opeatecall="opeateCall" />
-    <CallMaterialsPop v-model="callBoxStatus" />
+    <OperatePop v-model="callStatus" />
   </div>
 </template>
 
@@ -29,7 +28,6 @@
 import router from "@/router";
 import ScanCode from "@/views/process/components/scanCode.vue";
 import OperatePop from "../popUpView/operatePop.vue";
-import CallMaterialsPop from "../popUpView/callMaterialsPop.vue";
 const operationObjs: { icon?: string; text: string; num?: number }[] = [
   {
     icon: "liuzhuan",
@@ -58,10 +56,6 @@ const handleClick = (item: { text: string }) => {
 };
 
 const callStatus = ref(false);
-const callBoxStatus = ref(false);
-const opeateCall = () => {
-  callBoxStatus.value = true;
-};
 const call = () => {
   callStatus.value = true;
 };

+ 3 - 3
src/views/process/components/order.vue

@@ -36,13 +36,13 @@
       </div>
     </div>
     <!-- 右下角状态盒子 -->
-    <div class="statusBox">未开始</div>
+    <div class="statusBox">{{ dictS.getLableByValue("plan_work_order_state", item.workOrderState) }}</div>
   </div>
 </template>
 
 <script lang="ts" setup>
-import { reactive, ref } from "vue";
-
+import { useDictionaryStore } from "@/store";
+const dictS = useDictionaryStore();
 defineProps<{
   hoverStatus?: boolean;
   item: object;

+ 43 - 3
src/views/process/components/steps.vue

@@ -2,7 +2,9 @@
   <div class="body">
     <div class="steps" v-for="(item, index) in opsArray" :key="index" @click="boxClick(item, index)">
       <div :class="selectStepIndex == index
-          ? 'stepBox stepBoxHover'
+          ? item.exists == true
+            ? 'stepBox stepBoxHover'
+            : 'stepBox stepExistsHover'
           : item.opComplete
             ? 'stepBox stepBoxDisabled'
             : 'stepBox'
@@ -34,6 +36,9 @@
           {{ item.completeNum }}
         </div>
       </div>
+      <div v-if="item.exists != true && selectStepIndex == index" class="existsText">
+        注:该工位在计划上未分配此工序任务!
+      </div>
       <div class="line" v-if="index != opsArray.length - 1"></div>
     </div>
     <el-empty v-if="!opsArray" description="暂无数据" />
@@ -42,11 +47,24 @@
 
 <script lang="ts" setup>
 import { useProcessStore } from "@/store";
+import { emitter, EventsNames } from "@/utils/common";
 const store = useProcessStore();
 const props = defineProps<{
   opsArray?: object;
 }>();
-const selectStepIndex = ref(0);
+//步骤显示index
+const selectStepIndex = ref(null);
+const emitFnc = () => {
+  emitter.emit(EventsNames.PROCESS_STEPOBJ, {
+    index: selectStepIndex.value,
+    lastStatus:
+      selectStepIndex.value == null || selectStepIndex.value == 0
+        ? false
+        : props.opsArray[selectStepIndex.value - 1].opComplete == false
+          ? true
+          : false,
+  });
+};
 const setStepIndex = () => {
   for (let i = 0; i < props.opsArray.length; i++) {
     if (props.opsArray[i].opComplete == false) {
@@ -61,16 +79,27 @@ const boxClick = (item, index) => {
   store.processInfo.operationCode = item.operationCode;
   store.processInfo.operationName = item.operationName;
   selectStepIndex.value = index;
+  emitFnc();
 };
 watch(
   () => props.opsArray,
   () => {
     if (props.opsArray.length > 0) {
+      selectStepIndex.value = null;
       setStepIndex();
-      boxClick(props.opsArray[selectStepIndex.value], selectStepIndex.value);
+      if (selectStepIndex.value !== null) {
+        boxClick(props.opsArray[selectStepIndex.value], selectStepIndex.value);
+      } else {
+        emitFnc();
+      }
+    } else {
+      selectStepIndex.value = null;
     }
   }
 );
+onBeforeUnmount(() => {
+  emitter.off(EventsNames.PROCESS_STEPOBJ);
+});
 </script>
 
 <style lang="scss" scoped>
@@ -78,6 +107,13 @@ watch(
   width: 100%;
 }
 
+.existsText {
+  margin-left: 40px;
+  font-size: $f16;
+  font-weight: 500;
+  color: red;
+}
+
 .stepBox {
   display: flex;
   justify-content: space-between;
@@ -93,6 +129,10 @@ watch(
   background-color: $select-hover;
 }
 
+.stepExistsHover {
+  background-color: red;
+}
+
 .stepBoxDisabled {
   background-color: grey;
 }

+ 7 - 1
src/views/process/orders.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="commonTitle">待完成订单[{{ ordersSum }}]</div>
+  <div class="commonTitle">待完成订单[{{ ordersSum }}]</div>
   <Empty v-if="ordersDataArray.length < 1" />
   <el-scrollbar class="barHeight">
     <Order v-for="(item, index) in ordersDataArray" :key="index" @click="setSlectIndex(index)"
@@ -12,6 +12,7 @@ import Order from "@/views/process/components/order.vue";
 import { useProcessStore } from "@/store";
 
 const store = useProcessStore();
+const selectSeqIndex = inject("selectSeqIndex");
 const props = defineProps<{
   ordersSum?: number;
 }>();
@@ -25,6 +26,11 @@ const setSlectIndex = (value: number) => {
   store.odersData.workOrderCode = ordersDataArray.value[value].workOrderCode;
   store.processInfo.materialName = ordersDataArray.value[value].materialName;
   store.processInfo.materialModel = ordersDataArray.value[value].materialModel;
+  store.odersData.operationId = "";
+  store.processInfo.operationCode = "";
+  store.processInfo.operationName = "";
+  store.useSeqNo = "";
+  selectSeqIndex.value = null;
   emit("getindex", value);
 };
 

+ 0 - 40
src/views/process/popUpView/callMaterialsPop.vue

@@ -1,40 +0,0 @@
-<template>
-  <div class="midPopUp" v-if="modelValue">
-    <div class="container">
-    </div>
-  </div>
-</template>
-
-<script lang="ts" setup>
-
-const porps = defineProps({
-  modelValue: {
-    type: Boolean,
-    default: false,
-  },
-});
-const emits = defineEmits(["update:modelValue"]);
-</script>
-
-<style lang="scss" scoped>
-.titleText {
-  text-align: center;
-}
-
-.container {
-  height: 50vh;
-  width: 40vw;
-  background-color: #ffffff60;
-  display: flex;
-  justify-content: space-between;
-  flex-direction: row;
-  flex-wrap: nowrap;
-  padding: 24px;
-}
-
-.active {
-  background-image: url("@/assets/images/caijiwancheng.png");
-  background-position: right top;
-  background-repeat: no-repeat;
-}
-</style>

+ 57 - 7
src/views/process/popUpView/operatePop.vue

@@ -1,38 +1,77 @@
 <template>
   <div class="midPopUp" @click="emits('update:modelValue', false)" v-if="modelValue">
     <div class="container" @click.stop>
-      <div class="operatorBox">
+      <div :class="lcDisabled ? 'operatorBox disableOp' : 'operatorBox'" @click="lastOpCall">
         <div>
           <div class="titleText">流程叫料</div>
           <div class="describeText">(向上一流程工序呼叫流程物料)</div>
         </div>
       </div>
 
-      <div class="operatorBox" @click="opeateCall">
+      <div :class="gxDisabled ? 'operatorBox disableOp' : 'operatorBox'" @click="opeateCall">
         <div>
           <div class="titleText">工序叫料</div>
           <div class="describeText">(向本工序呼叫涉及物料)</div>
         </div>
       </div>
     </div>
-    
   </div>
 </template>
 
 <script lang="ts" setup>
-
-const porps = defineProps({
+import { useProcessStore } from "@/store";
+import { emitter, EventsNames } from "@/utils/common";
+import { callItems } from "@/api/process";
+const store = useProcessStore();
+const router = useRouter();
+const props = defineProps({
   modelValue: {
     type: Boolean,
     default: false,
   },
 });
-const emits = defineEmits(["update:modelValue",'opeatecall']);
+const emits = defineEmits(["update:modelValue"]);
+const gxDisabled = ref(false);
+const lcDisabled = ref(false);
 const callBoxStatus = ref(false);
+//工序叫料
 const opeateCall = () => {
-  emits("opeatecall");
+  if (gxDisabled.value) return;
+  router.push({ name: "call-materiel" });
   emits("update:modelValue", false);
 };
+const callLast = async () => {
+  const { data } = await callItems({
+    operationId,
+    seqNo,
+  });
+};
+//流程叫料
+const lastOpCall = () => {
+  if (lcDisabled.value) return;
+};
+//监听工序index等
+emitter.on(EventsNames.PROCESS_STEPOBJ, (data: any) => {
+  if (data.index == null) {
+    lcDisabled.value = true;
+    gxDisabled.value = true;
+  } else {
+    if (data.lastStatus == false) {
+      lcDisabled.value = true;
+    } else {
+      lcDisabled.value = false;
+    }
+    gxDisabled.value = false;
+  }
+});
+watch(
+  () => props.modelValue,
+  () => {
+    if (store.useSeqNo == "") {
+      lcDisabled.value = true;
+    }
+  }
+);
 </script>
 
 <style lang="scss" scoped>
@@ -50,6 +89,17 @@ const opeateCall = () => {
   flex-wrap: nowrap;
   padding: 24px;
 
+  .disableOp {
+    opacity: 0.6;
+    background-color: red !important;
+    color: white;
+    cursor: not-allowed !important;
+
+    .describeText {
+      color: white;
+    }
+  }
+
   .operatorBox {
     width: 50%;
     height: 100%;

+ 1 - 1
src/views/traceability/components/materials.vue

@@ -34,7 +34,7 @@ const getPagination = async () => {
   });
   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]);