From 33bdc00cdee41fa0e8d315f4bb2c3fc13ed0df10 Mon Sep 17 00:00:00 2001
From: haoxuan <haoxuan>
Date: 星期四, 02 十一月 2023 19:30:50 +0800
Subject: [PATCH] Merge branch 'dev' of http://192.168.5.5:10010/r/web/bulletin-board-style1 into wn

---
 src/views/dashboard/index.vue                       |  209 ++++++++++++++++
 src/views/dashboard/components/TaskControlModal.vue |  561 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 770 insertions(+), 0 deletions(-)

diff --git a/src/views/dashboard/components/TaskControlModal.vue b/src/views/dashboard/components/TaskControlModal.vue
new file mode 100644
index 0000000..c51b154
--- /dev/null
+++ b/src/views/dashboard/components/TaskControlModal.vue
@@ -0,0 +1,561 @@
+<template>
+  <div class="task-control-modal">
+    <BaseModal v-model="modelData" :wider="false">
+      <template #title>
+        {{ !['涓嬪彂鍙傛暟鎴愬姛', '涓嬪彂鍙傛暟澶辫触'].includes(state.value as string) ? '鏂颁换鍔�' : '鎻愮ず' }}
+      </template>
+      <div class="modal-content">
+        <template v-if="['鍒濆鍖�', '璁℃椂涓�', '鍑嗗鐢熶骇', '涓嬪彂鍙傛暟涓�'].includes(state.value as string)">
+          <div class="content-title">
+            <div class="content-title-item">褰撳墠浠诲姟锛歿{ task?.Procedure.procedure.procedureName || '' }}</div>
+            <div class="content-title-item">
+              鐢熶骇鏁伴噺锛�
+              <div class="leaf-shape">
+                {{ task?.Order?.amount || 0 }}
+              </div>
+            </div>
+          </div>
+
+          <div class="content-scroll">
+            <div class="scroll-container">
+              <el-scrollbar always class="scroller">
+                <template v-if="task">
+                  <div class="info">
+                    <div class="info-item">璁㈠崟缂栧彿锛歿{ task.Order.orderId || '' }}</div>
+                    <div class="info-item">宸ュ崟缂栧彿锛歿{ task.Order.workOrderId || '' }}</div>
+                    <div class="info-item">浜у搧鍚嶇О锛歿{ task.Order.productName || '' }}</div>
+                    <div class="info-item">鏁伴噺锛歿{ task.Order.amount || 0 }}{{ task.Order.unit }}</div>
+                    <div class="info-item">浜よ揣鏃ユ湡锛歿{ task.Order.deliverDate || '' }}</div>
+                    <div class="info-item">宸ユ椂锛� {{ task.Procedure.procedure.workHours || '' }}</div>
+                    <div class="info-item">
+                      璁″垝鏃堕棿锛� {{ formatDate(task.Procedure.startTime) || '' }}
+                      -
+                      {{ formatDate(task.Procedure.endTime) }}
+                    </div>
+
+                    <div class="info-item">瀹㈡埛鍚嶇О锛歿{ task.Order.customer || '' }}</div>
+                    <div class="info-item info-item-two">閫氶亾锛� {{ CHANNEL_NAME_MAP[task.Channel] || '' }}</div>
+
+                    <div class="info-item info-item-two">鍙傛暟瑕佹眰锛歿{ task.Order.parameter || '' }}</div>
+
+                    <div class="info-item-two">
+                      <div style="color: #4efefa; font-size: 18px; margin-bottom: 10px; margin-top: 20px">宸ヨ壓鍙傛暟</div>
+                      <div v-for="(item, index) in craftParams" :key="index" class="info-item info-item-two">
+                        {{ item.Key }}锛歿{ item.Value || '' }}
+                      </div>
+                    </div>
+                  </div>
+                </template>
+              </el-scrollbar>
+            </div>
+          </div>
+        </template>
+
+        <!--        鍙湁鑾峰彇鍒板伐鑹哄弬鏁版墠鍙互杩涜鎿嶄綔-->
+        <template v-if="getCraftParamsTip">
+          <div class="content-tips">
+            <div class="craft-params-error">
+              <div class="error-icon">
+                <el-icon size="90" color="red"><CircleCloseFilled /></el-icon>
+              </div>
+              <div class="error-tip">{{ getCraftParamsTip }}</div>
+            </div>
+          </div>
+        </template>
+
+        <template v-else>
+          <div v-if="['璁℃椂涓�', '鍑嗗鐢熶骇'].includes(state.value as string)" class="content-tips">
+            <div class="prepare">
+              <div class="countdown">
+                <div class="alert-light">
+                  <div class="light" :class="{ blink: state.value === '璁℃椂涓�' }"></div>
+                </div>
+                <div class="time">
+                  <div class="time-label">----- 鍓╀綑鏃堕棿 -----</div>
+                  <div class="time-text">00:{{ countdown30s.formattedTime.value }}</div>
+                </div>
+              </div>
+              <div class="safe-tip">
+                {{ safeProduce }}
+              </div>
+            </div>
+          </div>
+
+          <div v-if="['涓嬪彂鍙傛暟涓�'].includes(state.value as string)" class="content-tips">
+            <div class="delivery">
+              <div class="delivery-tip">宸ヨ壓鍙傛暟涓嬪彂涓�...</div>
+              <div class="delivery-progress">
+                <el-progress :text-inside="true" :stroke-width="30" :percentage="50" status="success" />
+              </div>
+            </div>
+          </div>
+
+          <div v-if="['涓嬪彂鍙傛暟鎴愬姛'].includes(state.value as string)" class="delivery-success-tips">
+            <div class="success-icon">
+              <el-icon size="90" color="green"><SuccessFilled /></el-icon>
+            </div>
+            <div class="success-tip">{{ deliveryTip }}</div>
+            <div class="success-sub-tip">{{ countdown3s.remainingSeconds }}s</div>
+          </div>
+
+          <div v-if="['涓嬪彂鍙傛暟澶辫触'].includes(state.value as string)" class="delivery-error-tips">
+            <div class="error-icon">
+              <el-icon size="90" color="red"><CircleCloseFilled /></el-icon>
+            </div>
+            <div class="error-tip">{{ deliveryTip }}</div>
+            <div class="error-sub-tip">璇烽噸璇�</div>
+          </div>
+        </template>
+      </div>
+      <template #footer>
+        <template v-if="getCraftParamsTip">
+          <div class="btn">
+            <BigButton bg-color="#4765c0" @click="closeModal"> 鍏抽棴 </BigButton>
+          </div>
+        </template>
+
+        <template v-else>
+          <div class="btn">
+            <BigButton
+              v-if="!['涓嬪彂鍙傛暟鎴愬姛', '涓嬪彂鍙傛暟澶辫触'].includes(state.value as string)"
+              bg-color="#4765c0"
+              @click="respiteProduce"
+            >
+              鏆傜紦鐢熶骇
+            </BigButton>
+            <BigButton
+              v-if="['鍒濆鍖�', '璁℃椂涓�'].includes(state.value as string)"
+              color="#0d0d0d"
+              :disabled="state.value === '璁℃椂涓�'"
+              @click="prepareProduce"
+            >
+              鐢熶骇鍑嗗
+            </BigButton>
+            <BigButton v-if="state.value === '鍑嗗鐢熶骇'" bg-color="#4efefa" @click="startProduce"> 寮�濮嬬敓浜� </BigButton>
+            <BigButton v-if="state.value === '涓嬪彂鍙傛暟涓�'" bg-color="#4efefa">
+              <el-icon class="is-loading" color="#000">
+                <Loading />
+              </el-icon>
+            </BigButton>
+            <BigButton v-if="state.value === '涓嬪彂鍙傛暟澶辫触'" bg-color="#4765c0" @click="deliverParams">
+              鍐嶆涓嬪彂
+            </BigButton>
+            <BigButton v-if="state.value === '涓嬪彂鍙傛暟鎴愬姛'" bg-color="#4765c0" @click="closeModal"> 鍏抽棴 </BigButton>
+          </div>
+        </template>
+      </template>
+    </BaseModal>
+  </div>
+</template>
+<script setup lang="ts">
+import type { CraftParam, Task } from '@/api/task'
+import { useDateFormat, useVModel } from '@vueuse/core'
+import { ref, toRefs, watch } from 'vue'
+import BigButton from '@/views/dashboard/components/BigButton.vue'
+import { CHANNEL_NAME_MAP } from '@/common/constants'
+import { getCraftParams, sendProcessParams } from '@/api'
+import { useCountDown } from '@/common/composable'
+import { storeToRefs } from 'pinia'
+import { useTasksStore } from '@/stores/tasks'
+import { createMachine } from 'xstate'
+import { useMachine } from '@xstate/vue'
+import { CircleCloseFilled, Loading, SuccessFilled } from '@element-plus/icons-vue'
+
+export interface TaskControlModalProps {
+  task?: Task
+  /** 鏄惁灞曠ず妯℃�佹 */
+  modelValue: boolean
+}
+const props = withDefaults(defineProps<TaskControlModalProps>(), {
+  task: undefined,
+  modelValue: false
+})
+const emit = defineEmits<{
+  'update:modelValue': [show: boolean]
+  /** 涓嬪彂鎴愬姛鍚庤Е鍙�, 鐢ㄤ簬澶栭儴鑾峰緱鍒锋柊鏁版嵁鐨勬椂鏈� */
+  produceStart: []
+}>()
+
+const modelData = useVModel(props, 'modelValue', emit)
+
+const { task } = toRefs(props)
+
+/**
+ * 鏍煎紡鍖栨椂闂存埑
+ * @param timestamp 鍚庣杩旂殑10浣嶆椂闂存埑
+ */
+function formatDate(timestamp?: number) {
+  if (!timestamp) {
+    return '--'
+  }
+  const time = useDateFormat(timestamp * 1000, 'YYYY-MM-DD', { locales: 'zh-cn' })
+  return time.value
+}
+
+// 宸ヨ壓鍙傛暟
+const craftParams = ref<CraftParam[]>()
+// 鑾峰彇宸ヨ壓鍙傛暟缁撴灉淇℃伅
+const getCraftParamsTip = ref('')
+
+/**
+ * 鑾峰彇褰撳墠灞曠ず鐨勪换鍔$殑宸ヨ壓鍙傛暟
+ */
+function getTaskProduceParams(taskId?: number) {
+  if (taskId) {
+    craftParams.value = []
+    getCraftParamsTip.value = ''
+    getCraftParams({ id: taskId }).then(
+      (res) => {
+        craftParams.value = res.data.Params ?? []
+        getCraftParamsTip.value = ''
+      },
+      (err) => {
+        console.error(err)
+        craftParams.value = []
+        getCraftParamsTip.value = '鑾峰彇宸ヨ壓鍙傛暟澶辫触锛�'
+      }
+    )
+  }
+}
+
+watch(modelData, () => {
+  // 寮圭獥鏄剧ず鏃惰幏鍙栧伐鑹哄弬鏁�
+  if (modelData.value) {
+    getTaskProduceParams(task?.value?.Procedure?.ID)
+  } else {
+    reset()
+  }
+})
+
+const countdown30s = useCountDown(30, {
+  onEnd: () => {
+    send('缁撴潫璁℃椂')
+  }
+})
+
+// 寮圭獥鏃惰幏鍙栧畨鍏ㄧ敓浜ф彁绀烘枃鏈�
+const { channels } = storeToRefs(useTasksStore())
+const safeProduce = ref('')
+watch(modelData, () => {
+  if (modelData.value) {
+    safeProduce.value = channels?.value?.[task?.value?.Channel ?? 0]?.Prompt?.safeProduce ?? ''
+  }
+})
+
+/**
+ * 閲嶇疆寮圭獥缂撳瓨鐘舵��
+ */
+function reset() {
+  countdown30s.reset()
+  countdown3s.reset()
+  getCraftParamsTip.value = ''
+  deliveryTip.value = ''
+}
+
+/**
+ * 鎸夐挳鐘舵�佹満
+ * 鍙互鍘� https://stately.ai/registry/new?mode=Design 鏌ョ湅鐘舵�佽浆鎹㈠浘
+ */
+const toggleMachine = createMachine({
+  id: 'produce',
+  initial: '鍒濆鍖�',
+  predictableActionArguments: true,
+  states: {
+    鍒濆鍖�: {
+      on: {
+        寮�濮嬭鏃�: { target: '璁℃椂涓�' },
+        缁撴潫: { target: '鍒濆鍖�' }
+      }
+    },
+    璁℃椂涓�: {
+      on: {
+        缁撴潫璁℃椂: { target: '鍑嗗鐢熶骇' },
+        鏆傜紦鐢熶骇: { target: '鍒濆鍖�' }
+      }
+    },
+    鍑嗗鐢熶骇: {
+      on: {
+        寮�濮嬬敓浜�: { target: '涓嬪彂鍙傛暟涓�' },
+        鏆傜紦鐢熶骇: { target: '鍒濆鍖�' }
+      }
+    },
+    涓嬪彂鍙傛暟涓�: {
+      on: {
+        鎴愬姛: { target: '涓嬪彂鍙傛暟鎴愬姛' },
+        澶辫触: { target: '涓嬪彂鍙傛暟澶辫触' },
+        鏆傜紦鐢熶骇: { target: '鍒濆鍖�' }
+      }
+    },
+    涓嬪彂鍙傛暟鎴愬姛: {
+      on: {
+        缁撴潫: {
+          target: '鍒濆鍖�'
+        }
+      }
+    },
+    涓嬪彂鍙傛暟澶辫触: {
+      on: {
+        鍐嶆涓嬪彂: { target: '鍑嗗鐢熶骇' }
+      }
+    }
+  }
+})
+const { state, send } = useMachine(toggleMachine)
+
+/**
+ * 鏆傜紦鐢熶骇, 鐩存帴鍏抽棴寮圭獥
+ */
+function respiteProduce() {
+  modelData.value = false
+  send('鏆傜紦鐢熶骇')
+  reset()
+}
+/**
+ * 鐢熶骇鍑嗗
+ */
+function prepareProduce() {
+  send('寮�濮嬭鏃�')
+  countdown30s.startCountdown()
+}
+
+// 鍙傛暟涓嬪彂鎴愬姛鎴栧け璐ョ粨鏋�
+const deliveryTip = ref('')
+
+// 鍙傛暟涓嬪彂鎴愬姛鍚庡欢鏃�3绉掑悗鍏抽棴寮圭獥
+const countdown3s = useCountDown(3, {
+  onEnd: () => {
+    closeModal()
+  }
+})
+
+/**
+ * 寮�濮嬬敓浜� , 涓嬪彂宸ヨ壓鍙傛暟
+ */
+function startProduce() {
+  send('寮�濮嬬敓浜�')
+
+  sendProcessParams({
+    procedureId: task!.value!.Procedure.ID
+  })
+    .then(
+      (res) => {
+        deliveryTip.value = '涓嬪彂鎴愬姛'
+        send('鎴愬姛')
+        countdown3s.startCountdown()
+      },
+      (err) => {
+        console.error(err)
+        deliveryTip.value = err.msg ? err.msg : '鎶辨瓑锛屽伐搴忎笅鍙戝け璐ワ紒'
+        send('澶辫触')
+      }
+    )
+    .finally(() => {})
+}
+
+/**
+ * 鍐嶆涓嬪彂
+ */
+function deliverParams() {
+  send('鍐嶆涓嬪彂')
+}
+
+/**
+ * 鍏抽棴寮圭獥
+ */
+function closeModal() {
+  modelData.value = false
+  send('缁撴潫')
+  reset()
+  emit('produceStart')
+}
+</script>
+<style scoped lang="scss">
+.modal-content {
+  height: 550px;
+}
+.content-scroll {
+  height: 350px;
+  overflow: hidden;
+}
+.content-tips {
+  height: 120px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  padding: 0 40px;
+}
+
+@keyframes blink {
+  from {
+    opacity: 1;
+  }
+  50% {
+    opacity: 1;
+  }
+  51% {
+    opacity: 0;
+  }
+  to {
+    opacity: 0;
+  }
+}
+.prepare {
+  width: 100%;
+  .safe-tip {
+    width: 100%;
+    text-align: center;
+    color: red;
+    font-size: 30px;
+    margin-top: 10px;
+    background-color: #142974;
+  }
+}
+.countdown {
+  color: #fff;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  .alert-light {
+    margin-right: 20px;
+    .light {
+      height: 56px;
+      width: 56px;
+      background-color: red;
+      border-radius: 50%;
+    }
+    .light.blink {
+      animation: blink 800ms infinite;
+    }
+  }
+  .time {
+    .time-text {
+      text-align: center;
+      font-size: 20px;
+      font-weight: 600;
+    }
+  }
+}
+:deep(.el-dialog__body) {
+  padding: 0 20px;
+}
+.btn {
+  display: flex;
+  align-items: center;
+  justify-content: space-around;
+}
+.content-title {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 10px 40px;
+}
+.content-title-item {
+  width: 50%;
+  font-size: 20px;
+  color: #4efefa;
+}
+
+.leaf-shape {
+  position: relative;
+  display: inline-block;
+  width: 140px;
+  height: 46px;
+  border-radius: 23px 0 23px 0;
+  text-align: center;
+  line-height: 46px;
+  color: #fff;
+  background: url('/leaf-shape.png') no-repeat center center / cover;
+}
+.scroll-container {
+  margin: 0 auto;
+  padding: 10px 20px;
+  width: calc(100% - 40px);
+  height: 340px;
+}
+.info {
+  display: flex;
+  align-items: center;
+  flex-wrap: wrap;
+  background-color: #0e246a;
+  padding: 10px 20px;
+}
+.info-item {
+  width: 50%;
+  height: 35px;
+  line-height: 35px;
+  font-size: 16px;
+  color: #fff;
+}
+.info-item-two {
+  width: 100%;
+}
+
+.delivery-success-tips {
+  padding-top: 140px;
+  color: #fff;
+
+  height: 100%;
+  width: 100%;
+  .success-icon {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+  .success-tip {
+    margin-top: 50px;
+    text-align: center;
+    font-size: 30px;
+  }
+  .success-sub-tip {
+    margin-top: 10px;
+    font-size: 30px;
+    text-align: center;
+  }
+}
+.delivery-error-tips {
+  padding-top: 140px;
+  color: #fff;
+
+  height: 100%;
+  width: 100%;
+  .error-icon {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+  .error-tip {
+    margin-top: 50px;
+    text-align: center;
+    font-size: 30px;
+  }
+  .error-sub-tip {
+    margin-top: 10px;
+    font-size: 20px;
+    text-align: center;
+  }
+}
+
+.delivery {
+  height: 100%;
+  width: 100%;
+  padding: 0 90px;
+  .delivery-tip {
+    text-align: center;
+    font-size: 30px;
+    color: red;
+  }
+  .delivery-progress {
+    margin-top: 8px;
+  }
+}
+.craft-params-error {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  flex-direction: column;
+  .error-tip {
+    font-size: 18px;
+    color: #fff;
+  }
+}
+</style>
diff --git a/src/views/dashboard/index.vue b/src/views/dashboard/index.vue
new file mode 100644
index 0000000..815948f
--- /dev/null
+++ b/src/views/dashboard/index.vue
@@ -0,0 +1,209 @@
+<template>
+  <DashboardLayout>
+    <template #leftBlock1>
+      <TaskTabs v-model="activeTaskTab" style="margin-top: 20px" :list="taskTabsList" @change="changeTab"></TaskTabs>
+    </template>
+    <template #leftBlock2>
+      <ChannelCollapse :channels="channels"></ChannelCollapse>
+    </template>
+    <template #middleBlock1>
+      <DashboardTitle></DashboardTitle>
+    </template>
+    <template #middleBlock2>
+      <el-tabs v-model="activeMainTabName" class="main-info-tabs">
+        <el-tab-pane label="鍔犲伐淇℃伅" name="鍔犲伐淇℃伅">
+          <ProcessingInfo style="margin-top: 6px" :task="activeTask"></ProcessingInfo>
+        </el-tab-pane>
+        <el-tab-pane label="宸ヨ壓淇℃伅" name="宸ヨ壓淇℃伅">
+          <ProcessInfo
+            v-for="item in craftModelStore.craftModelList"
+            :key="item.ID"
+            :craft-model="item"
+            @detail="openCraftModelDetailModal"
+          ></ProcessInfo>
+        </el-tab-pane>
+        <el-tab-pane label="鐗╂枡娓呭崟" name="鐗╂枡娓呭崟">
+          <InputMaterialsList></InputMaterialsList>
+          <OutputMaterialsList></OutputMaterialsList>
+        </el-tab-pane>
+      </el-tabs>
+    </template>
+    <template #middleBlock3>
+      <SubTitle>浠诲姟璇︽儏</SubTitle>
+      <div class="task-detail">
+        <TaskControl :task="activeTask" @should-reload="reloadAllData"></TaskControl>
+      </div>
+      <ColorInfo :order="order" :type="1"></ColorInfo>
+      <ColorInfo :order="order" :type="2"></ColorInfo>
+    </template>
+    <template #middleBlock4>
+      <SubTitle>浜哄憳淇℃伅</SubTitle>
+      <PersonInfo v-for="worker in workers" :key="worker.workerId" :person="worker"></PersonInfo>
+    </template>
+    <template #rightBlock1>
+      <div class="date-time">
+        <CurrentDateTime></CurrentDateTime>
+      </div>
+    </template>
+    <template #rightBlock2>
+      <DeviceStatusInfo :plc="plcStore.plcInfo" :type="1"></DeviceStatusInfo>
+      <DeviceStatusInfo :device="deviceStore.deviceInfo" :type="2"></DeviceStatusInfo>
+      <DeviceNumberInfo></DeviceNumberInfo>
+    </template>
+    <template #rightBlock3>
+      <SubTitle>鐭ヨ瘑搴�</SubTitle>
+      <KnowledgeInfo></KnowledgeInfo>
+      <BigButton class="btn" bg-color="red">绾㈢伅鍛煎彨</BigButton>
+    </template>
+  </DashboardLayout>
+  <CraftDetailModal v-model="showCraftModelDetail" @close="showCraftModelDetail = false"></CraftDetailModal>
+</template>
+<script setup lang="ts">
+import { computed, ref, watch } from 'vue'
+import ChannelCollapse from '@/views/dashboard/components/ChannelCollapse.vue'
+import type { Worker, Order, Task } from '@/api/task'
+import PersonInfo from '@/views/dashboard/components/PersonInfo.vue'
+import ProcessInfo from '@/views/dashboard/components/ProcessInfo.vue'
+import ColorInfo from '@/views/dashboard/components/ColorInfo.vue'
+import DeviceStatusInfo from '@/views/dashboard/components/DeviceStatusInfo.vue'
+import DeviceNumberInfo from '@/views/dashboard/components/DeviceNumberInfo.vue'
+import KnowledgeInfo from '@/views/dashboard/components/KnowledgeInfo.vue'
+import InputMaterialsList from '@/views/dashboard/components/InputMaterialsList.vue'
+import OutputMaterialsList from '@/views/dashboard/components/OutputMaterialsList.vue'
+import BigButton from '@/views/dashboard/components/BigButton.vue'
+import type { LabelValue } from '@/views/dashboard/components/TaskTabs.vue'
+import TaskTabs from '@/views/dashboard/components/TaskTabs.vue'
+import CurrentDateTime from '@/views/dashboard/components/CurrentDateTime.vue'
+import { useTasksStore } from '@/stores/tasks'
+import { storeToRefs } from 'pinia'
+import ProcessingInfo from '@/views/dashboard/components/ProcessingInfo.vue'
+import TaskControl from '@/views/dashboard/components/TaskControl.vue'
+import SubTitle from '@/views/dashboard/components/SubTitle.vue'
+import DashboardTitle from '@/views/dashboard/components/DashboardTitle.vue'
+import { usePLCStore } from '@/stores/plc'
+import { useDevicesStore } from '@/stores/devices'
+import { useCraftModelStore } from '@/stores/craftModel'
+import CraftDetailModal from '@/views/dashboard/components/CraftDetailModal.vue'
+
+defineOptions({
+  name: 'DashboardView'
+})
+
+// 鑾峰彇褰撳墠楂樹寒浠诲姟鐨勫�肩彮浜轰俊鎭�
+const taskStore = useTasksStore()
+const workers = computed(() => {
+  return taskStore.activeTask?.Procedure?.procedure?.workers ?? []
+})
+
+const process = computed(() => {
+  return { product: '浜у搧鍚嶇О', number: '111', procedure: '宸ヨ壓鍚嶇О', isUpdate: true } as any
+})
+
+const order = computed(() => {
+  return {
+    finishNumber: 0,
+    unit: '涓�',
+    amount: '10'
+  } as unknown as Order
+})
+
+const taskTabsList = [
+  {
+    label: '鏈畬鎴�',
+    value: 1
+  },
+  {
+    label: '浠婃棩浠诲姟',
+    value: 2
+  },
+  {
+    label: '宸插畬鎴�',
+    value: 3
+  }
+]
+const activeTaskTab = ref(1)
+const activeMainTabName = ref<string>('鍔犲伐淇℃伅')
+
+const tasksStore = useTasksStore()
+const { activeTask, channels } = storeToRefs(tasksStore)
+tasksStore.getChannels(1)
+
+function changeTab(tab: LabelValue) {
+  tasksStore.getChannels(tab.value)
+}
+
+/**
+ * 瀹屾垚浠诲姟鎴栬�呬笅鍙戝弬鏁版垚鍔熷悗瑕佸埛鏂伴�氶亾鏁版嵁
+ * @param task
+ */
+function reloadAllData(task: Task) {
+  tasksStore.reload(task.Channel)
+}
+// 鍚姩plc 杞
+const plcStore = usePLCStore()
+plcStore.startPollingPLC()
+// 鍚姩 璁惧 杞
+const deviceStore = useDevicesStore()
+deviceStore.startPollingDevice()
+
+// 鍒囨崲浠诲姟鏃惰幏鍙栧搴斾换鍔$殑宸ヨ壓妯″瀷淇℃伅
+const craftModelStore = useCraftModelStore()
+watch(activeTask, () => {
+  craftModelStore.getCraftModelList()
+})
+
+const showCraftModelDetail = ref(false)
+function openCraftModelDetailModal() {
+  console.log(1)
+  showCraftModelDetail.value = true
+}
+</script>
+
+<style scoped lang="scss">
+$active-tab-color: #00dfdf;
+.date-time {
+  width: 100%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  padding-top: 12px;
+}
+:deep(.el-tabs) {
+  height: 100%;
+}
+:deep(.el-tab-pane) {
+  height: 100%;
+}
+:deep(.el-tabs__content) {
+  height: calc(100% - 56px);
+}
+:deep(.el-tabs__item) {
+  color: #fff;
+  font-size: 20px;
+}
+:deep(.el-tabs__nav-scroll) {
+  height: 46px;
+}
+:deep(.el-tabs__nav) {
+  height: 46px;
+}
+:deep(.el-step__title.is-process) {
+  color: #fff;
+}
+
+:deep(.el-tabs__item.is-active) {
+  color: $active-tab-color;
+  font-weight: 600;
+}
+:deep(.el-tabs__active-bar) {
+  background-color: $active-tab-color;
+  height: 4px;
+}
+:deep(.el-tabs__nav-wrap::after) {
+  height: 1px;
+}
+.btn {
+  width: 100%;
+  font-size: 20px;
+}
+</style>

--
Gitblit v1.8.0