From 1c22b65361d81ef23bd76d0f76a3dce7ef72fd99 Mon Sep 17 00:00:00 2001
From: haoxuan <haoxuan>
Date: 星期二, 31 十月 2023 10:06:56 +0800
Subject: [PATCH] 拉代码

---
 src/views/dashboard/components/TaskTabs.vue        |   25 +
 src/views/dashboard/components/ProcessingInfo.vue  |  220 ++++++++++++++++++++
 src/api/task.ts                                    |   10 
 src/views/dashboard/components/ChannelCollapse.vue |   58 ++++
 src/views/dashboard/components/CraftInfo.vue       |   10 
 src/views/dashboard/components/PersonInfo.vue      |    8 
 src/components.d.ts                                |   11 
 src/stores/tasks.ts                                |  106 +++++++++
 src/api/index.ts                                   |   39 ++
 src/api/plc.ts                                     |    6 
 src/components/DashboardLayout.vue                 |   40 ++
 /dev/null                                          |   87 -------
 vite.config.ts                                     |    2 
 src/views/dashboard/components/TaskInfo.vue        |   24 +
 14 files changed, 500 insertions(+), 146 deletions(-)

diff --git a/src/api/index.ts b/src/api/index.ts
index 1c5ab52..1517ce2 100644
--- a/src/api/index.ts
+++ b/src/api/index.ts
@@ -1,5 +1,6 @@
 import { request } from '@/common/utils'
-import type { TasksResponse } from './task'
+import type { TasksGroupByChannel } from './task'
+import type { PLCResponse } from './plc'
 
 export interface BaseResponse<T = any> {
   code: number
@@ -7,16 +8,38 @@
   msg: string
 }
 
+export interface TaskListParams {
+  /** 1鏈畬鎴�2浠婂ぉ鏈畬鎴�3宸插畬鎴� */
+  type: 1 | 2 | 3
+  /** 閫氶亾鍙� 涓嶄紶鏌ユ墍鏈夐�氶亾鐨� */
+  channel?: number
+  /** 浠庣鍑犱釜寮�濮嬫煡锛屼粠0寮�濮� */
+  offset: number
+  /** 鏌ュ灏戞潯 */
+  limit: number
+}
+
 /**
  * 鑾峰彇浠诲姟鍒楄〃
- * @param taskMode 1: 寰呯敓浜х殑浠诲姟 2: 鐪嬫澘鍚勯�氶亾褰撳墠灞曠ず鐨勪换鍔�
+ * @param params
  */
-export function getTaskList(taskMode: 1 | 2) {
-  return request<BaseResponse<TasksResponse>>({
-    url: '/v1/task/get',
+export function getTaskList(params: TaskListParams) {
+  return request<BaseResponse<TasksGroupByChannel>>({
+    url: '/v1/task/list',
     method: 'get',
-    params: {
-      taskMode
-    }
+    params
+  })
+}
+
+export interface ProductProgressParams {
+  channel: number
+  procedureId: number
+}
+
+export function getProductProgress(params: ProductProgressParams) {
+  return request<BaseResponse<PLCResponse>>({
+    url: '/v1/plc/productProgress',
+    method: 'post',
+    data: params
   })
 }
diff --git a/src/api/plc.ts b/src/api/plc.ts
new file mode 100644
index 0000000..686879e
--- /dev/null
+++ b/src/api/plc.ts
@@ -0,0 +1,6 @@
+export interface PLCResponse {
+  finishNumber: number
+  totalNumber: number
+  /** 1鏂紑 2鐢熶骇涓� 3寰呮満*/
+  plcStatus: 1 | 2 | 3
+}
diff --git a/src/api/task.ts b/src/api/task.ts
index a939691..405d0b4 100644
--- a/src/api/task.ts
+++ b/src/api/task.ts
@@ -48,7 +48,7 @@
   workHours: string
   inputMaterials: string
   outputMaterials: string
-  workers: Workers[]
+  workers: Worker[]
   allProcedureNames: string[]
   channel: number
 }
@@ -62,7 +62,7 @@
   CanStarted: boolean
 }
 
-export interface Workers {
+export interface Worker {
   workerId: string
   workerName: string
   phoneNum: string
@@ -78,7 +78,11 @@
 export interface TasksResponse {
   Tasks: Task[]
   TaskCount: number
-  workers: Workers[]
+  workers: Worker[]
   Prompt: Prompt
   ChannelAmount: number
 }
+
+export interface TasksGroupByChannel {
+  [channel: number]: TasksResponse
+}
diff --git a/src/components.d.ts b/src/components.d.ts
index 52bea60..fac83df 100644
--- a/src/components.d.ts
+++ b/src/components.d.ts
@@ -7,13 +7,8 @@
 
 declare module 'vue' {
   export interface GlobalComponents {
-    DashboardLayout: typeof import('./components/DashboardLayout.vue')['default']
-    ElButton: typeof import('element-plus/es')['ElButton']
-    ElCollapse: typeof import('element-plus/es')['ElCollapse']
-    ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
-    ElIcon: typeof import('element-plus/es')['ElIcon']
-    ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
-    RouterLink: typeof import('vue-router')['RouterLink']
-    RouterView: typeof import('vue-router')['RouterView']
+    DashboardLayout: (typeof import('./components/DashboardLayout.vue'))['default']
+    RouterLink: (typeof import('vue-router'))['RouterLink']
+    RouterView: (typeof import('vue-router'))['RouterView']
   }
 }
diff --git a/src/components/DashboardLayout.vue b/src/components/DashboardLayout.vue
index 692c86f..e3d5309 100644
--- a/src/components/DashboardLayout.vue
+++ b/src/components/DashboardLayout.vue
@@ -5,8 +5,8 @@
         <slot name="leftBlock1"></slot>
       </div>
       <div class="double-height-block padding-4">
-        <div class="card">
-          <el-scrollbar always>
+        <div class="card scroll-card">
+          <el-scrollbar always class="scroller">
             <slot name="leftBlock2"></slot>
           </el-scrollbar>
         </div>
@@ -16,18 +16,18 @@
       <div class="header-block padding-4">
         <slot name="middleBlock1"></slot>
       </div>
-      <div class="base-block padding-4">
+      <div class="top-block padding-4">
         <div class="card">
           <slot name="middleBlock2"></slot>
         </div>
       </div>
-      <div class="block-container">
-        <div class="base-block padding-4">
+      <div class="bottom-block">
+        <div class="bottom-block-item padding-4">
           <div class="card">
             <slot name="middleBlock3"></slot>
           </div>
         </div>
-        <div class="base-block padding-4">
+        <div class="bottom-block-item padding-4">
           <div class="card">
             <slot name="middleBlock4"></slot>
           </div>
@@ -67,6 +67,10 @@
 $baseBlockHeight: calc((100vh - 2 * $layoutPadding - $headerBlockHeight) / 2);
 // 鍙屽�嶉珮甯冨眬鍧楅珮搴�
 $doubleBlockHeight: calc($baseBlockHeight * 2);
+// 涓婅竟鍥哄畾楂�
+$topBlocHeight: 400px;
+// 涓嬭竟楂樺害
+$bottomBlockHeight: calc(100vh - 2 * $layoutPadding - $headerBlockHeight - $topBlocHeight);
 .dashboard-layout {
   display: flex;
   align-items: center;
@@ -100,14 +104,24 @@
 .padding-4 {
   padding: 6px;
 }
-.block-container {
+
+.base-block {
+  height: $baseBlockHeight;
+  flex: 1;
+}
+.top-block {
+  height: $topBlocHeight;
+  flex: 0;
+}
+.bottom-block {
   display: flex;
   align-items: center;
   justify-content: space-between;
+  height: $bottomBlockHeight;
 }
-.base-block {
-  height: $baseBlockHeight;
-  flex-grow: 1;
+.bottom-block-item {
+  height: $bottomBlockHeight;
+  flex: 1;
 }
 .header-block {
   height: $headerBlockHeight;
@@ -123,4 +137,10 @@
   border-radius: 6px;
   padding: 10px 16px;
 }
+.scroll-card {
+  padding: 0;
+}
+.scroller {
+  padding: 10px 16px;
+}
 </style>
diff --git a/src/stores/tasks.ts b/src/stores/tasks.ts
new file mode 100644
index 0000000..8f8599d
--- /dev/null
+++ b/src/stores/tasks.ts
@@ -0,0 +1,106 @@
+import { computed, ref } from 'vue'
+import { defineStore } from 'pinia'
+import type { Task, TasksGroupByChannel, TasksResponse } from '@/api/task'
+import type { TaskListParams } from '@/api'
+import { getTaskList } from '@/api'
+
+export interface ChannelMoreBtnStatus {
+  /** true 浠诲姟鏈姞杞藉畬  false 鎵�鏈変换鍔″凡缁忓姞杞藉畬鎴�*/
+  [channel: number]: boolean
+}
+
+export const useTasksStore = defineStore('tasks', () => {
+  const channels = ref<TasksGroupByChannel>({})
+
+  const currentType = ref<1 | 2 | 3>(1)
+
+  /**
+   * 鑾峰彇浠诲姟鏁版嵁
+   * @param type 1鏈畬鎴�2浠婂ぉ鏈畬鎴�3宸插畬鎴�
+   */
+  function getChannels(type: 1 | 2 | 3) {
+    currentType.value = type
+    const params: TaskListParams = {
+      type,
+      offset: 0,
+      limit: 3
+    }
+    getTaskList(params)
+      .then((res) => {
+        channels.value = res.data
+      })
+      .catch((err) => {
+        console.error(err)
+        channels.value = []
+      })
+  }
+
+  function moreChannelTasksBtn(channelNumber: number) {
+    const taskLength = channels.value[channelNumber].Tasks?.length ?? 0
+    const params: TaskListParams = {
+      type: currentType.value,
+      channel: channelNumber,
+      offset: taskLength,
+      limit: 10
+    }
+    getTaskList(params)
+      .then((res) => {
+        const existTasks = channels.value![channelNumber].Tasks ?? []
+        channels.value[channelNumber] = res.data[channelNumber] ?? {}
+        channels.value[channelNumber].Tasks = channels.value[channelNumber].Tasks ?? []
+        channels.value[channelNumber].Tasks = [...existTasks, ...channels.value[channelNumber].Tasks]
+      })
+      .catch((err) => {
+        console.error(err)
+      })
+  }
+
+  function foldChannelTasksBtn(channelNumber: number) {
+    const tasks = channels.value[channelNumber].Tasks ?? []
+    channels.value[channelNumber].Tasks = tasks.slice(0, 3)
+  }
+
+  const moreBtnStatus = computed(() => {
+    return Object.entries(channels.value).reduce((pre, currentValue) => {
+      const channelNumber = +currentValue[0]
+      const channelData = currentValue[1] as TasksResponse
+      pre[channelNumber] = channelData.TaskCount > (channelData.Tasks?.length ?? 0)
+      return pre
+    }, {} as ChannelMoreBtnStatus)
+  })
+
+  /** 褰撳墠楂樹寒鐨勪换鍔� */
+  const activeTask = ref<Task>()
+  function setActiveTask(task: Task) {
+    activeTask.value = task
+  }
+
+  const requestParamsMap = ref<{
+    [channel: number]: TaskListParams
+  }>({})
+  function getParamsByChannel(channel: number) {
+    return (
+      requestParamsMap.value[channel] ?? {
+        type: 1,
+        offset: 0,
+        limit: 3
+      }
+    )
+  }
+
+  function setParamsByChannel(channel: number, params: TaskListParams) {
+    requestParamsMap.value[channel] = params
+  }
+  return {
+    channels,
+    getChannels,
+    moreBtnStatus,
+    activeTask,
+    setActiveTask,
+    requestParamsMap,
+    getParamsByChannel,
+    setParamsByChannel,
+    moreChannelTasksBtn,
+    foldChannelTasksBtn
+  }
+})
diff --git a/src/views/dashboard/components/ChannelCollapse.vue b/src/views/dashboard/components/ChannelCollapse.vue
index 693ab61..bde2dd9 100644
--- a/src/views/dashboard/components/ChannelCollapse.vue
+++ b/src/views/dashboard/components/ChannelCollapse.vue
@@ -2,35 +2,61 @@
   <div class="channel-collapse">
     <el-collapse v-model="activeChannel">
       <el-collapse-item
-        v-for="(tasks, channelNumber) in channels"
+        v-for="(channel, channelNumber) in channels"
         :key="channelNumber"
         :title="CHANNEL_NAME_MAP[channelNumber] + ' 閫氶亾'"
         :name="String(channelNumber)"
       >
-        <TaskInfo v-for="task in tasks" :key="task.Procedure.ID" :task="task"></TaskInfo>
+        <TaskInfo
+          v-for="task in channel.Tasks"
+          :key="task.Procedure.ID"
+          :active="task.Procedure.ID === tasksStore.activeTask?.Procedure.ID"
+          :task="task"
+          style="margin-bottom: 16px"
+          @click="tasksStore.setActiveTask(task)"
+        ></TaskInfo>
+
+        <div
+          v-show="channel.Tasks?.length && tasksStore.moreBtnStatus?.[channelNumber]"
+          class="btn more"
+          @click="tasksStore.moreChannelTasksBtn(channelNumber)"
+        >
+          鏌ョ湅鏇村
+          <el-icon style="margin-left: 6px"><ArrowDownBold /></el-icon>
+        </div>
+
+        <div
+          v-show="channel.Tasks?.length && !tasksStore.moreBtnStatus?.[channelNumber]"
+          class="btn fold"
+          @click="tasksStore.foldChannelTasksBtn(channelNumber)"
+        >
+          鏀惰捣
+          <el-icon style="margin-left: 6px"><ArrowUpBold /></el-icon>
+        </div>
       </el-collapse-item>
     </el-collapse>
   </div>
 </template>
 <script setup lang="ts">
 import { ref, watchEffect } from 'vue'
-import type { Task } from '@/api/task'
+import type { TasksGroupByChannel } from '@/api/task'
 import TaskInfo from './TaskInfo.vue'
 import { CHANNEL_NAME_MAP } from '@/common/constants'
-
-export interface Channel {
-  [channelNumber: number]: Task[]
-}
+import { useTasksStore } from '@/stores/tasks'
+import { ArrowDownBold, ArrowUpBold } from '@element-plus/icons-vue'
 
 export interface ChannelCollapseProps {
-  channels: Channel
+  channels: TasksGroupByChannel
 }
 
 const props = defineProps<ChannelCollapseProps>()
 const activeChannel = ref<string[]>([])
 
+const tasksStore = useTasksStore()
+
 watchEffect(() => {
-  const channelNumbers = Object.keys(props.channels).sort((a, b) => +a - +b)
+  // 閫氶亾鏁版嵁鍙樺寲鍚�
+  const channelNumbers = Object.keys(props?.channels ?? {}).sort((a, b) => +a - +b)
   activeChannel.value = [...channelNumbers]
 })
 </script>
@@ -66,4 +92,18 @@
   font-size: 16px;
   font-weight: 600;
 }
+
+.btn {
+  width: 70%;
+  height: 50px;
+  margin: 0 auto;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  border-radius: 6px;
+  font-size: 18px;
+  font-weight: 600;
+  cursor: pointer;
+  background: linear-gradient(to right, rgb(29, 96, 212) 0%, rgb(47, 122, 251), rgb(29, 96, 212) 100%);
+}
 </style>
diff --git a/src/views/dashboard/components/ProcessInfo.vue b/src/views/dashboard/components/CraftInfo.vue
similarity index 92%
rename from src/views/dashboard/components/ProcessInfo.vue
rename to src/views/dashboard/components/CraftInfo.vue
index a75e342..3ebac61 100644
--- a/src/views/dashboard/components/ProcessInfo.vue
+++ b/src/views/dashboard/components/CraftInfo.vue
@@ -1,5 +1,5 @@
 <template>
-  <div class="process-info">
+  <div class="craft-info">
     <div class="item-l-bng">
       <img src="~@/assets/images/process-model.png" />
     </div>
@@ -9,7 +9,7 @@
       <div class="item-r-b">{{ process.name }}</div>
     </div>
     <div class="tip-r">
-      <img src="~@/assets/images/process-tip.png" />
+      <img src="~@/assets/images/process-tip.png" alt="" />
     </div>
     <div class="tip-current">褰撳墠浣跨敤</div>
     <div class="btn">
@@ -18,7 +18,9 @@
   </div>
 </template>
 <script setup lang="ts">
-import { computed, toRefs } from 'vue'
+// 宸ヨ壓淇℃伅
+import { toRefs } from 'vue'
+
 export interface ProcessInfoProps {
   process: process
 }
@@ -33,7 +35,7 @@
 .font_weight {
   font-weight: 600;
 }
-.process-info {
+.craft-info {
   width: calc(50% - 35px);
   height: 110px;
   padding: 23px 10px 10px;
diff --git a/src/views/dashboard/components/PersonInfo.vue b/src/views/dashboard/components/PersonInfo.vue
index d054728..95693e4 100644
--- a/src/views/dashboard/components/PersonInfo.vue
+++ b/src/views/dashboard/components/PersonInfo.vue
@@ -29,10 +29,12 @@
   </div>
 </template>
 <script setup lang="ts">
-import type { UserFilled } from '@element-plus/icons-vue'
-import { computed, toRefs } from 'vue'
+import { StarFilled, UserFilled } from '@element-plus/icons-vue'
+import { toRefs } from 'vue'
+import type { Worker } from '@/api/task'
+
 export interface PersonInfoProps {
-  person: person
+  person: Worker
 }
 
 const props = defineProps<PersonInfoProps>()
diff --git a/src/views/dashboard/components/ProcessingInfo.vue b/src/views/dashboard/components/ProcessingInfo.vue
new file mode 100644
index 0000000..6aaf8d9
--- /dev/null
+++ b/src/views/dashboard/components/ProcessingInfo.vue
@@ -0,0 +1,220 @@
+<template>
+  <div class="processing-info">
+    <div class="step">
+      <el-steps
+        v-if="task?.AllProcedures"
+        :active="task.CurrentProcedureIndex ?? 0"
+        finish-status="success"
+        class="steps"
+      >
+        <el-step v-for="(item, index) in task.AllProcedures" :key="index" icon="" :title="item"></el-step>
+      </el-steps>
+    </div>
+    <div class="details">
+      <div class="row">
+        <div class="col">宸ュ崟缂栧彿: {{ task?.Order?.workOrderId || '' }}</div>
+        <div class="col">璁㈠崟缂栧彿: {{ task?.Order?.orderId || '' }}</div>
+      </div>
+
+      <div class="row">
+        <div class="col">浜у搧鍚嶇О: {{ task?.Order?.productName || '--' }}</div>
+        <div class="col">鏁伴噺: {{ task?.Order?.amount || 0 }}{{ task?.Order?.unit }}</div>
+      </div>
+      <div class="row">
+        <div class="col">浜よ揣鏃ユ湡: {{ task?.Order?.deliverDate || '--' }}</div>
+        <div class="col">宸ユ椂: {{ task?.Procedure?.procedure?.workHours || '--' }}</div>
+      </div>
+      <div class="row">
+        <div class="col">
+          璧锋鏃堕棿: {{ formatDate(task?.Procedure?.startTime) }}
+          ~
+          {{ formatDate(task?.Procedure?.endTime) }}
+        </div>
+        <div class="col">閫氶亾: {{ isNumber(task?.Channel) ? CHANNEL_NAME_MAP[task?.Channel] : '--' }}</div>
+      </div>
+      <div class="row">
+        <div class="col">瀹㈡埛鍚嶇О: {{ task?.Order?.customer || '' }}</div>
+        <div class="col">鍙傛暟瑕佹眰: {{ task?.Order?.parameter || '' }}</div>
+      </div>
+    </div>
+    <div class="process">
+      <div>瀹屾垚杩涘害:</div>
+      <div class="process-bar">
+        <el-progress
+          define-back-color="#132f6e"
+          color="#00cc66"
+          text-color="#fff"
+          :text-inside="true"
+          :stroke-width="30"
+          :percentage="processingPercent"
+        ></el-progress>
+      </div>
+    </div>
+  </div>
+</template>
+<script setup lang="ts">
+// 鍔犲伐淇℃伅缁勪欢
+import type { Task } from '@/api/task'
+import { computed, onUnmounted, toRefs, watch } from 'vue'
+import { useDateFormat } from '@vueuse/core'
+import { useRequest } from 'vue-hooks-plus'
+import { getProductProgress } from '@/api'
+import type { ProductProgressParams } from '@/api'
+import { isNumber } from 'lodash-es'
+import { CHANNEL_NAME_MAP } from '@/common/constants'
+
+const props = defineProps<{
+  task?: Task
+}>()
+
+const { task } = toRefs(props)
+export interface Statistics {
+  totalNumber: number
+  finishNumber: number
+}
+
+/**
+ * 璁$畻鐢熶骇杩涘害
+ * @param statistics
+ * @return 杩涘害,0~100
+ */
+function calculateProgress(statistics: Statistics): number {
+  if (!statistics) {
+    return 0
+  }
+
+  if (statistics.finishNumber === 0) {
+    return 0
+  }
+  if (statistics.finishNumber === statistics.totalNumber) {
+    return 100
+  }
+
+  const result = Math.floor((statistics.finishNumber / statistics.totalNumber) * 100)
+  return result > 100 ? 100 : result
+}
+
+/**
+ * 璁$畻瀹屾垚杩涘害, 浠诲姟鐘舵�佹湭鐢熶骇鍥哄畾涓� 0% 宸插畬鎴愬浐瀹氫负 100% 鐢熶骇涓垯浠巔lc鑾峰彇
+ */
+const processingPercent = computed(() => {
+  if (task?.value?.Procedure?.Status === 1) {
+    return 0
+  }
+
+  if (task?.value?.Procedure?.Status === 3) {
+    return 100
+  }
+
+  if (task?.value?.Procedure?.Status === 2) {
+    return calculateProgress(plcResponse?.value?.data as Statistics)
+  }
+
+  return 0
+})
+
+/**
+ * 濡傛灉浠诲姟鐘舵�佹槸杩涜涓�, 鍒欒疆璇� plc 鍙栬繘搴�
+ */
+const {
+  data: plcResponse,
+  run: startPLCPolling,
+  cancel: cancelPLCPolling
+} = useRequest(
+  () =>
+    getProductProgress({
+      channel: task?.value?.Channel,
+      procedureId: task?.value?.Procedure.ID
+    } as ProductProgressParams),
+  {
+    manual: true,
+    pollingInterval: 6000,
+    pollingWhenHidden: false
+  }
+)
+
+/**
+ * 浠诲姟鐘舵�佹槸鐢熶骇涓垯杞plc鍙栫洰鏍囨暟鍜屽畬鎴愭暟璁$畻瀹屾垚杩涘害
+ */
+watch(
+  () => task?.value,
+  () => {
+    cancelPLCPolling()
+    if (task?.value?.Procedure?.Status === 2) {
+      startPLCPolling()
+    }
+  }
+)
+
+onUnmounted(() => {
+  cancelPLCPolling()
+})
+
+/**
+ * 鏍煎紡鍖栨椂闂存埑
+ * @param timestamp 鍚庣杩旂殑10浣嶆椂闂存埑
+ */
+function formatDate(timestamp?: number) {
+  if (!timestamp) {
+    return '--'
+  }
+  const time = useDateFormat(timestamp * 1000, 'YYYY-MM-DD', { locales: 'zh-cn' })
+  return time.value
+}
+</script>
+<style scoped lang="scss">
+$text-color: #d7d7ca;
+
+.step {
+  width: 100%;
+  height: 66px;
+  overflow-x: auto;
+  margin-top: -5px;
+  padding: 0 20px;
+  .steps {
+    height: 100%;
+    .el-step__icon {
+      width: 16px;
+      height: 16px;
+    }
+    .el-step__title {
+      line-height: 25px;
+      font-size: 14px;
+    }
+    .el-step__title.is-process {
+      color: #a8abb2;
+    }
+  }
+}
+.details {
+  font-size: 18px;
+  padding: 10px 20px;
+  color: $text-color;
+  .row {
+    width: 100%;
+    padding: 2px 0;
+    display: flex;
+    align-items: center;
+  }
+  .col {
+    width: 50%;
+    flex: 1;
+  }
+}
+.process {
+  font-size: 18px;
+  padding: 10px 20px;
+  color: $text-color;
+  display: flex;
+}
+.process-bar {
+  flex: 1;
+  margin-left: 20px;
+}
+:deep(.el-progress-bar__outer) {
+  border-radius: 8px;
+}
+:deep(.el-progress-bar__inner) {
+  border-radius: 8px;
+}
+</style>
diff --git a/src/views/dashboard/components/TaskInfo.vue b/src/views/dashboard/components/TaskInfo.vue
index e085d73..d0ba6e1 100644
--- a/src/views/dashboard/components/TaskInfo.vue
+++ b/src/views/dashboard/components/TaskInfo.vue
@@ -1,5 +1,5 @@
 <template>
-  <div class="task-info" :class="{ selected }">
+  <div class="task-info" :class="{ active }">
     <div
       class="task-info-title"
       :class="{
@@ -31,13 +31,13 @@
 
 export interface TaskInfoProps {
   task: Task
-  selected?: boolean
+  active?: boolean
 }
 
 const props = withDefaults(defineProps<TaskInfoProps>(), {
-  selected: false
+  active: false
 })
-const { task, selected } = toRefs(props)
+const { task, active } = toRefs(props)
 
 const planTimeText = computed(() => {
   const format = (date: number) => {
@@ -56,9 +56,12 @@
 $status-ready: #13235a;
 $status-done: #13235a;
 $text-color: #d7d7d7;
+$active-color: #00dfdf;
 .task-info {
   background-color: #6b83ff;
   border-radius: 4px;
+  overflow: initial;
+  cursor: pointer;
 }
 .task-info-title {
   height: 34px;
@@ -94,4 +97,17 @@
     flex: 1;
   }
 }
+.active {
+  position: relative;
+  &:before {
+    content: '';
+    width: 8px;
+    background-color: $active-color;
+    height: 100%;
+    position: absolute;
+    top: 0;
+    left: 0;
+    border-radius: 6px 0 0 6px;
+  }
+}
 </style>
diff --git a/src/views/dashboard/components/TaskTabs.vue b/src/views/dashboard/components/TaskTabs.vue
index d2e3311..4eaf64f 100644
--- a/src/views/dashboard/components/TaskTabs.vue
+++ b/src/views/dashboard/components/TaskTabs.vue
@@ -1,32 +1,39 @@
 <template>
   <div class="task-tabs">
     <div
-      v-for="tabName in list"
-      :key="tabName"
+      v-for="tab in list"
+      :key="tab.value"
       class="task-tab-item triangle-tip"
-      :class="{ active: props.modelValue === tabName }"
-      @click="selectTab(tabName)"
+      :class="{ active: props.modelValue === tab.value }"
+      @click="selectTab(tab)"
     >
-      {{ tabName }}
+      {{ tab.label }}
     </div>
   </div>
 </template>
 <script setup lang="ts">
 import { useVModel } from '@vueuse/core'
 
+export interface LabelValue {
+  label: string
+  value: any
+}
+
 const props = defineProps<{
   /** tab 鍒楄〃*/
-  list: string[]
+  list: LabelValue[]
   /** 褰撳墠閫変腑鐨� tab*/
-  modelValue?: string
+  modelValue?: any
 }>()
 const emit = defineEmits<{
   'update:modelValue': [tabName: string]
+  change: [tab: LabelValue]
 }>()
 const data = useVModel(props, 'modelValue', emit)
 
-function selectTab(tabName: string) {
-  data.value = tabName
+function selectTab(tab: LabelValue) {
+  data.value = tab.value
+  emit('change', tab)
 }
 </script>
 <style scoped lang="scss">
diff --git a/src/views/dashboard/index.vue b/src/views/dashboard/index.vue
deleted file mode 100644
index b927f26..0000000
--- a/src/views/dashboard/index.vue
+++ /dev/null
@@ -1,87 +0,0 @@
-<template>
-  <DashboardLayout>
-    <template #leftBlock1>
-      <TaskTabs v-model="activeTaskTab" style="margin-top: 20px" :list="taskTabsTitle"></TaskTabs>
-    </template>
-    <template #leftBlock2>
-      <ChannelCollapse :channels="channels"></ChannelCollapse>
-    </template>
-    <template #middleBlock1>鏍囬</template>
-    <template #middleBlock2
-      >涓荤湅鏉�
-      <ProcessInfo :process="process"></ProcessInfo>
-    </template>
-    <template #middleBlock3>浠诲姟璇︽儏</template>
-    <template #middleBlock4
-      >浜哄憳淇℃伅
-      <PersonInfo :person="person"></PersonInfo>
-    </template>
-    <template #rightBlock1>
-      <div class="date-time">
-        <CurrentDateTime></CurrentDateTime>
-      </div>
-    </template>
-    <template #rightBlock2>鐘舵�侀潰鏉�</template>
-    <template #rightBlock3>鐭ヨ瘑搴�</template>
-  </DashboardLayout>
-</template>
-<script setup lang="ts">
-import { getTaskList } from '@/api'
-import { computed, ref, watchEffect } from 'vue'
-import ChannelCollapse from '@/views/dashboard/components/ChannelCollapse.vue'
-import type { Task } from '@/api/task'
-import { chain } from 'lodash-es'
-import ProcessInfo from '@/views/dashboard/components/ProcessInfo.vue'
-import PersonInfo from '@/views/dashboard/components/PersonInfo.vue'
-import TaskTabs from '@/views/dashboard/components/TaskTabs.vue'
-import CurrentDateTime from '@/views/dashboard/components/CurrentDateTime.vue'
-
-defineOptions({
-  name: 'DashboardView'
-})
-
-const taskList = ref<Task[]>()
-
-function getChannels() {
-  getTaskList(2)
-    .then((res) => {
-      taskList.value = res.data.Tasks
-    })
-    .catch((err) => {
-      console.error(err)
-      taskList.value = []
-    })
-}
-
-const channels = computed(() => {
-  return chain<Task>(taskList.value)
-    .groupBy((ele) => ele.Channel)
-    .value()
-})
-const process = computed(() => {
-  return { name: '宸ヨ壓鍚嶇О', number: '111' }
-})
-const person = computed(() => {
-  return {
-    workerName: '濮撳悕',
-    phone: '111'
-  }
-})
-getChannels()
-const taskTabsTitle = ['鏈畬鎴�', '浠婃棩浠诲姟', '宸插畬鎴�']
-const activeTaskTab = ref('鏈畬鎴�')
-
-watchEffect(() => {
-  // console.log(activeTaskTab?.value, 111111)
-})
-</script>
-
-<style scoped>
-.date-time {
-  width: 100%;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  padding-top: 12px;
-}
-</style>
diff --git a/vite.config.ts b/vite.config.ts
index 692b8dc..a45bed3 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -14,7 +14,7 @@
   server: {
     proxy: {
       '/v1/': {
-        target: 'http://192.168.20.4:8003',
+        target: 'http://192.168.20.119:8003',
         ws: true,
         changeOrigin: true
       }

--
Gitblit v1.8.0