From 2bb9a863e75312fe90869ea3deea137b46b1bb1e Mon Sep 17 00:00:00 2001
From: haoxuan <haoxuan>
Date: 星期一, 06 十一月 2023 17:46:43 +0800
Subject: [PATCH] 拉代码

---
 src/views/dashboard/components/TaskControl.vue     |   14 +-
 src/views/dashboard/components/CurrentDateTime.vue |    3 
 src/views/dashboard/components/TaskStep.vue        |   71 ++++++++++++++
 src/components.d.ts                                |    1 
 src/stores/tasks.ts                                |   11 +
 src/api/index.ts                                   |   24 ++++
 src/components/CommonModal.vue                     |    2 
 src/stores/craftModel.ts                           |   41 +++++++-
 src/views/dashboard/components/DeviceCheckList.vue |   81 +++++++++++----
 index.html                                         |    2 
 src/stores/devices.ts                              |    9 -
 public/favicon.ico                                 |    0 
 src/views/dashboard/components/DashboardTitle.vue  |   31 +++++-
 13 files changed, 234 insertions(+), 56 deletions(-)

diff --git a/index.html b/index.html
index 39aff6e..28e6a80 100644
--- a/index.html
+++ b/index.html
@@ -4,7 +4,7 @@
     <meta charset="UTF-8" />
     <link rel="icon" href="/favicon.ico" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <title>鐪嬫澘</title>
+    <title>鏅鸿兘宸ヤ綔鍙�</title>
   </head>
   <body>
     <div id="app"></div>
diff --git a/public/favicon.ico b/public/favicon.ico
index df36fcf..765befd 100644
--- a/public/favicon.ico
+++ b/public/favicon.ico
Binary files differ
diff --git a/src/api/index.ts b/src/api/index.ts
index 6b41213..e474d51 100644
--- a/src/api/index.ts
+++ b/src/api/index.ts
@@ -11,6 +11,13 @@
   msg: string
 }
 
+export interface ListResponse<T = any> {
+  code: number
+  data: T
+  msg: string
+  total: number
+}
+
 export interface TaskListParams {
   /** 1鏈畬鎴�2浠婂ぉ鏈畬鎴�3宸插畬鎴� */
   type: 1 | 2 | 3
@@ -108,6 +115,21 @@
   })
 }
 
+export interface SetCurrentDeviceParams {
+  currentDeviceID: string
+}
+
+/**
+ * 鑾峰彇褰撳墠闈㈡澘缁戝畾鐨勮澶囧垪琛�
+ */
+export function apiSetCurrentDevice(data: SetCurrentDeviceParams) {
+  return request<BaseResponse<Devices>>({
+    url: `/v1/device/setCurrentDeviceId`,
+    method: 'post',
+    data
+  })
+}
+
 export interface CraftModelListParams {
   procedureId: number
   page: number
@@ -119,7 +141,7 @@
  * @param params
  */
 export function apiGetCraftModelList(params: CraftModelListParams) {
-  return request<BaseResponse<CraftModel[]>>({
+  return request<ListResponse<CraftModel[]>>({
     url: '/v1/processModel/list',
     method: 'get',
     params
diff --git a/src/components.d.ts b/src/components.d.ts
index 5374a8f..e028f6c 100644
--- a/src/components.d.ts
+++ b/src/components.d.ts
@@ -24,6 +24,7 @@
     ElSteps: typeof import('element-plus/es')['ElSteps']
     ElTabPane: typeof import('element-plus/es')['ElTabPane']
     ElTabs: typeof import('element-plus/es')['ElTabs']
+    ElText: typeof import('element-plus/es')['ElText']
     RouterLink: typeof import('vue-router')['RouterLink']
     RouterView: typeof import('vue-router')['RouterView']
   }
diff --git a/src/components/CommonModal.vue b/src/components/CommonModal.vue
index 372690b..43c79aa 100644
--- a/src/components/CommonModal.vue
+++ b/src/components/CommonModal.vue
@@ -28,7 +28,7 @@
   /** 鏄惁灞曠ず妯℃�佹 */
   modelValue: boolean
   /** 鏇村鐗堟湰 */
-  wider: boolean
+  wider?: boolean
 }
 const props = withDefaults(defineProps<BaseModalProps>(), {
   modelValue: false,
diff --git a/src/stores/craftModel.ts b/src/stores/craftModel.ts
index 9b8afbd..b550e86 100644
--- a/src/stores/craftModel.ts
+++ b/src/stores/craftModel.ts
@@ -1,22 +1,25 @@
-import { ref, watch } from 'vue'
+import { computed, ref, watch } from 'vue'
 import { defineStore } from 'pinia'
 import type { CraftModel } from '@/api/craftModel'
 import { apiGetCraftModelList } from '@/api'
 import { useTasksStore } from '@/stores/tasks'
 
 const watcher = ref()
-
+const page = ref(1)
+const total = ref(0)
 export const useCraftModelStore = defineStore('craftModel', () => {
-  const craftModelList = ref<CraftModel[]>()
+  const craftModelList = ref<CraftModel[]>([])
   const taskStore = useTasksStore()
   function getCraftModelList() {
     if (taskStore.activeTask?.Procedure.ID) {
+      craftModelList.value = []
       apiGetCraftModelList({
         procedureId: taskStore.activeTask?.Procedure.ID,
-        page: 1,
-        pageSize: 999
+        page: page.value,
+        pageSize: 6
       }).then((res) => {
         craftModelList.value = res.data ?? []
+        total.value = res.total
       })
     }
   }
@@ -25,10 +28,36 @@
     watch(
       () => taskStore.activeTask,
       () => {
+        page.value = 1
         getCraftModelList()
       }
     )
   }
 
-  return { craftModelList, getCraftModelList }
+  const loading = ref(false)
+
+  function loadMore() {
+    if (taskStore.activeTask?.Procedure.ID && !loading.value && hasMore.value) {
+      page.value++
+      loading.value = true
+      apiGetCraftModelList({
+        procedureId: taskStore.activeTask?.Procedure.ID,
+        page: page.value,
+        pageSize: 6
+      })
+        .then((res) => {
+          craftModelList.value = [...craftModelList.value, ...(res.data ?? [])]
+          total.value = res.total
+        })
+        .finally(() => {
+          loading.value = false
+        })
+    }
+  }
+
+  const hasMore = computed(() => {
+    return total.value > craftModelList.value.length
+  })
+
+  return { craftModelList, getCraftModelList, hasMore, loading, loadMore }
 })
diff --git a/src/stores/devices.ts b/src/stores/devices.ts
index fb0fd53..a23d468 100644
--- a/src/stores/devices.ts
+++ b/src/stores/devices.ts
@@ -1,4 +1,4 @@
-import { computed, onUnmounted } from 'vue'
+import { computed } from 'vue'
 import { defineStore } from 'pinia'
 import { getDeviceList } from '@/api'
 import { useRequest } from 'vue-hooks-plus'
@@ -7,6 +7,9 @@
 
 export const useDevicesStore = defineStore('device', () => {
   const deviceInfo = computed(() => {
+    if (deviceInfo?.value) {
+      deviceRes.value.data.currentDeviceID = 'wwwwwwww222222'
+    }
     return deviceRes?.value?.data as Devices
   })
 
@@ -27,10 +30,6 @@
     cancelDevicePolling()
     startDevicePolling()
   }
-
-  onUnmounted(() => {
-    cancelDevicePolling()
-  })
 
   return { deviceInfo, startPollingDevice }
 })
diff --git a/src/stores/tasks.ts b/src/stores/tasks.ts
index 3a97ead..e115738 100644
--- a/src/stores/tasks.ts
+++ b/src/stores/tasks.ts
@@ -77,10 +77,14 @@
   /**
    * 鍒锋柊鎵�鏈夋暟鎹�
    */
-  function reload(channel: number) {
+  function reloadChannel(channel: number) {
     getChannels(currentType.value).then(() => {
       autoSelectTask(channel)
     })
+  }
+
+  function reloadAllData() {
+    getChannels(currentType.value)
   }
 
   function moreChannelTasksBtn(channelNumber: number) {
@@ -128,9 +132,10 @@
     getChannels,
     moreBtnStatus,
     activeTask,
-    reload,
+    reloadChannel,
     setActiveTask,
     moreChannelTasksBtn,
-    foldChannelTasksBtn
+    foldChannelTasksBtn,
+    reloadAllData
   }
 })
diff --git a/src/views/dashboard/components/CurrentDateTime.vue b/src/views/dashboard/components/CurrentDateTime.vue
index 3097eab..2a41bcd 100644
--- a/src/views/dashboard/components/CurrentDateTime.vue
+++ b/src/views/dashboard/components/CurrentDateTime.vue
@@ -13,9 +13,8 @@
 $color: #30decd;
 
 .current-date-time {
-  width: 370px;
   color: $color;
-  font-size: 24px;
+  font-size: 20px;
   font-weight: 600;
 }
 </style>
diff --git a/src/views/dashboard/components/DashboardTitle.vue b/src/views/dashboard/components/DashboardTitle.vue
index 637ef35..015694a 100644
--- a/src/views/dashboard/components/DashboardTitle.vue
+++ b/src/views/dashboard/components/DashboardTitle.vue
@@ -1,29 +1,39 @@
 <template>
   <div class="dashboard-title">
     <div class="title-text">
-      鏅鸿兘宸ヤ綔鍙� 鈥� {{ deviceStore?.deviceInfo?.currentDeviceID ?? '' }}
+      鏅鸿兘宸ヤ綔鍙� 鈥�
+      <el-popover
+        placement="bottom"
+        :width="200"
+        trigger="click"
+        :content="deviceStore?.deviceInfo?.currentDeviceID ?? ''"
+      >
+        <template #reference>
+          <el-text truncated class="device-name">{{ deviceStore?.deviceInfo?.currentDeviceID ?? '' }}</el-text>
+        </template>
+      </el-popover>
       <el-icon size="32" color="#0db7f5" style="margin-left: 20px; cursor: pointer" @click="openDevicesModal">
         <IconSlider></IconSlider>
       </el-icon>
     </div>
     <div class="title-status">
       <div class="connection-info" @click="openProblemsModal">
-        <el-icon size="30" :color="problemsIconStatus ? '#00ff00' : '#ff0000'">
+        <el-icon size="26" :color="problemsIconStatus ? '#00ff00' : '#ff0000'">
           <AlertLightIcon></AlertLightIcon>
         </el-icon>
       </div>
       <div class="cloud-connection-status">
-        <el-icon v-if="cloudConnectionIconStatus" size="45" color="#00ff00">
+        <el-icon v-if="cloudConnectionIconStatus" size="38" color="#00ff00">
           <IconCloudDone></IconCloudDone>
         </el-icon>
 
-        <el-icon v-else size="45" color="#ff0000">
+        <el-icon v-else size="38" color="#ff0000">
           <IconCloudOff></IconCloudOff>
         </el-icon>
       </div>
     </div>
   </div>
-  <DeviceCheckList v-model="showDevicesModal" :devices="deviceList"></DeviceCheckList>
+  <DeviceCheckList v-model="showDevicesModal" @should-reload="emits('shouldReload')"></DeviceCheckList>
   <TroubleTrackerModal v-model="showProblemsModal" :problems="problemList"></TroubleTrackerModal>
 </template>
 <script setup lang="ts">
@@ -38,6 +48,10 @@
 import { useRequest } from 'vue-hooks-plus'
 import { apiGetProblemList } from '@/api'
 import { PROBLEMS_POLLING_DURATION } from '@/common/constants'
+
+const emits = defineEmits<{
+  shouldReload: []
+}>()
 
 // 鏄惁鏄剧ず闂璇婃柇modal
 const showProblemsModal = ref(false)
@@ -117,10 +131,15 @@
   align-items: center;
   position: absolute;
   top: 16px;
-  right: 40px;
+  right: 6px;
 }
 .connection-info {
   margin-right: 10px;
   cursor: pointer;
 }
+.device-name {
+  max-width: 340px;
+  font-size: 40px;
+  color: #fff;
+}
 </style>
diff --git a/src/views/dashboard/components/DeviceCheckList.vue b/src/views/dashboard/components/DeviceCheckList.vue
index 3091543..b63dfe5 100644
--- a/src/views/dashboard/components/DeviceCheckList.vue
+++ b/src/views/dashboard/components/DeviceCheckList.vue
@@ -4,18 +4,18 @@
       <template #title>璁惧閫夋嫨</template>
       <div class="device-box">
         <el-scrollbar always class="scroller">
-          <template v-if="devices?.length">
+          <template v-if="deviceInfo?.deviceIDList?.length">
             <div
-              v-for="(item, index) in devices"
+              v-for="(item, index) in deviceInfo?.deviceIDList"
               :key="index"
-              :class="item.checked ? 'device-item check-item' : 'device-item'"
-              @click="deviceClick(index)"
+              :class="selectedDevice === item ? 'device-item check-item' : 'device-item'"
+              @click="deviceClick(item)"
             >
               <div class="item-l">
-                <span>{{ item.number }}</span>
-                {{ item.name }}
+                <span>{{ item }}</span>
+                <!--  {{ item }}-->
               </div>
-              <div v-if="item.checked" class="item-r">
+              <div v-if="selectedDevice === item" class="item-r">
                 <el-icon class="item-icon" size="22" color="#00ff00"><CircleCheckFilled /></el-icon>
               </div>
             </div>
@@ -35,7 +35,11 @@
 import { useVModel } from '@vueuse/core'
 import { CircleCheckFilled } from '@element-plus/icons-vue'
 import BigButton from '@/views/dashboard/components/BigButton.vue'
-import { ref } from 'vue'
+import { useDevicesStore } from '@/stores/devices'
+import { storeToRefs } from 'pinia'
+import { ref, watch } from 'vue'
+import { apiSetCurrentDevice } from '@/api'
+import { ElMessage } from 'element-plus'
 export interface DeviceCheckListProps {
   modelValue: boolean
 }
@@ -45,28 +49,57 @@
 
 const emit = defineEmits<{
   'update:modelValue': [show: boolean]
+  shouldReload: []
 }>()
 const modelData = useVModel(props, 'modelValue', emit)
+const deviceStore = useDevicesStore()
+const { deviceInfo } = storeToRefs(deviceStore)
 
-const devices = ref([
-  {
-    number: '111',
-    name: '璁惧A',
-    checked: true
-  },
-  {
-    number: '222',
-    name: '璁惧b'
+// 寮圭獥鎵撳紑鏃惰瀹氬綋鍓嶉�変腑鐨勮澶�
+const selectedDevice = ref<string>('')
+watch(modelData, () => {
+  if (modelData.value) {
+    selectedDevice.value = deviceInfo.value?.currentDeviceID ?? ''
   }
-])
+})
+
+function deviceClick(deviceId: string) {
+  selectedDevice.value = deviceId
+}
+
+function saveModal() {
+  if (!selectedDevice.value) {
+    ElMessage({
+      message: '璇峰厛閫変腑涓�涓澶�',
+      type: 'error',
+      duration: 3 * 1000
+    })
+    return
+  }
+  apiSetCurrentDevice({ currentDeviceID: selectedDevice.value })
+    .then(() => {
+      ElMessage({
+        message: '璁惧畾鎴愬姛',
+        type: 'success',
+        duration: 2 * 1000
+      })
+      modelData.value = false
+      emit('shouldReload')
+    })
+    .catch((err) => {
+      console.error(err)
+      ElMessage({
+        message: err.msg,
+        type: 'error',
+        duration: 3 * 1000
+      })
+    })
+    .finally(() => {
+      deviceStore.startPollingDevice()
+    })
+}
 function closeModal() {
   modelData.value = false
-}
-function saveModal() {}
-const deviceClick = (index) => {
-  devices.value.find((ele) => (ele.checked = false))
-
-  devices.value[index].checked = true
 }
 </script>
 <style scoped lang="scss">
diff --git a/src/views/dashboard/components/TaskControl.vue b/src/views/dashboard/components/TaskControl.vue
index 47b9945..3d22b64 100644
--- a/src/views/dashboard/components/TaskControl.vue
+++ b/src/views/dashboard/components/TaskControl.vue
@@ -42,11 +42,7 @@
       </template>
     </div>
   </div>
-  <TaskControlModal
-    v-model="showTaskControlModal"
-    :task="task"
-    @produce-start="emit('shouldReload', task)"
-  ></TaskControlModal>
+  <TaskControlModal v-model="showTaskControlModal" :task="task" @produce-start="onProduceStart"></TaskControlModal>
 </template>
 <script setup lang="ts">
 import type { Task } from '@/api/task'
@@ -80,14 +76,14 @@
  * 瀹屾垚浠诲姟
  */
 function finishTaskProduce() {
-  if (task?.value?.Procedure?.ID) {
+  if (task?.value && task.value?.Procedure?.ID) {
     finishTask({ id: task!.value.Procedure.ID }).then(
       (res) => {
         ElMessage({
           message: '鎿嶄綔鎴愬姛锛�',
           type: 'success'
         })
-        emit('shouldReload', task.value)
+        emit('shouldReload', task.value as Task)
       },
       (err) => {
         console.error(err)
@@ -105,6 +101,10 @@
   }
 }
 
+function onProduceStart() {
+  emit('shouldReload', task!.value as Task)
+}
+
 /**
  * 鏍煎紡鍖栨椂闂存埑
  * @param timestamp 鍚庣杩旂殑10浣嶆椂闂存埑
diff --git a/src/views/dashboard/components/TaskStep.vue b/src/views/dashboard/components/TaskStep.vue
new file mode 100644
index 0000000..b9f02b6
--- /dev/null
+++ b/src/views/dashboard/components/TaskStep.vue
@@ -0,0 +1,71 @@
+<template>
+  <div class="task-step">
+    <div v-for="(item, index) in props.steps" :key="index" class="task-step-item" :style="{ 'flex-basis': flexBasis }">
+      <el-icon v-if="index + 1 < active" class="icon" size="22" color="#01f304"><CircleCheck /></el-icon>
+
+      <el-icon v-if="index + 1 === active" class="icon" size="22" color="#c25915"><Clock /></el-icon>
+      <el-icon v-if="index + 1 > active" class="icon" size="22" color="#7d7f83"><Clock /></el-icon>
+      <span class="text" :class="{ green: index + 1 < active, red: index + 1 === active, gray: index + 1 > active }">
+        {{ item }}
+      </span>
+      <span class="line"></span>
+    </div>
+  </div>
+</template>
+<script setup lang="ts">
+import { CircleCheck, Clock } from '@element-plus/icons-vue'
+import { computed } from 'vue'
+
+export interface TaskStepProps {
+  active: number
+  steps: string[]
+}
+const props = defineProps<TaskStepProps>()
+
+const flexBasis = computed(() => {
+  if (props.steps.length) {
+    return `${Math.floor((1 / props.steps.length) * 100)}%`
+  }
+  return '0'
+})
+</script>
+<style scoped lang="scss">
+.task-step {
+  display: flex;
+  align-items: center;
+}
+.task-step-item {
+  display: flex;
+  align-items: center;
+  flex: 1;
+  &:last-child {
+    flex-basis: auto !important;
+    flex-shrink: 0;
+    flex-grow: 0;
+    & > .line {
+      display: none;
+    }
+  }
+  .icon {
+    margin-right: 6px;
+  }
+  .green {
+    color: #01f304;
+  }
+  .red {
+    color: #c25915;
+  }
+  .gray {
+    color: #7d7f83;
+  }
+}
+.text {
+  flex-shrink: 0;
+}
+.line {
+  display: inline-block;
+  height: 1px;
+  background-color: #fff;
+  width: 100%;
+}
+</style>

--
Gitblit v1.8.0