feat: 通道展示组件添加查看更多逻辑;任务选中展示;添加加工信息组件
| | |
| | | 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 |
| | |
| | | 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 |
| | | }) |
| | | } |
New file |
| | |
| | | export interface PLCResponse { |
| | | finishNumber: number |
| | | totalNumber: number |
| | | /** 1断开 2生产中 3待机*/ |
| | | plcStatus: 1 | 2 | 3 |
| | | } |
| | |
| | | Prompt: Prompt |
| | | ChannelAmount: number |
| | | } |
| | | |
| | | export interface TasksGroupByChannel { |
| | | [channel: number]: TasksResponse |
| | | } |
| | |
| | | |
| | | 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'] |
| | | ElCollapse: (typeof import('element-plus/es'))['ElCollapse'] |
| | | ElCollapseItem: (typeof import('element-plus/es'))['ElCollapseItem'] |
| | | ElIcon: (typeof import('element-plus/es'))['ElIcon'] |
| | | ElProgress: (typeof import('element-plus/es'))['ElProgress'] |
| | | ElScrollbar: (typeof import('element-plus/es'))['ElScrollbar'] |
| | | ElStep: (typeof import('element-plus/es'))['ElStep'] |
| | | ElSteps: (typeof import('element-plus/es'))['ElSteps'] |
| | | ElTabPane: (typeof import('element-plus/es'))['ElTabPane'] |
| | | ElTabs: (typeof import('element-plus/es'))['ElTabs'] |
| | | RouterLink: (typeof import('vue-router'))['RouterLink'] |
| | | RouterView: (typeof import('vue-router'))['RouterView'] |
| | | } |
| | | } |
| | |
| | | <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> |
| | |
| | | $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; |
| | |
| | | .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; |
| | |
| | | import { ref } from 'vue' |
| | | import { computed, ref } from 'vue' |
| | | import { defineStore } from 'pinia' |
| | | import type { Task } from '@/api/task' |
| | | 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 |
| | | } |
| | | return { activeTask, setActiveTask } |
| | | |
| | | 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 |
| | | } |
| | | }) |
| | |
| | | <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" |
| | | 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' |
| | | import { useTasksStore } from '@/stores/tasks' |
| | | |
| | | export interface Channel { |
| | | [channelNumber: number]: Task[] |
| | | } |
| | | import { ArrowDownBold, ArrowUpBold } from '@element-plus/icons-vue' |
| | | |
| | | export interface ChannelCollapseProps { |
| | | channels: Channel |
| | | channels: TasksGroupByChannel |
| | | } |
| | | |
| | | const props = defineProps<ChannelCollapseProps>() |
| | |
| | | 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> |
| | |
| | | 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> |
File was renamed from src/views/dashboard/components/ProcessInfo.vue |
| | |
| | | <template> |
| | | <div class="process-info"> |
| | | <div class="craft-info"> |
| | | <div class="item-l-bng"> |
| | | <img src="~@/assets/images/process-model.png" /> |
| | | </div> |
| | |
| | | <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"> |
| | |
| | | </div> |
| | | </template> |
| | | <script setup lang="ts"> |
| | | import { computed, toRefs } from 'vue' |
| | | // 工艺信息 |
| | | import { toRefs } from 'vue' |
| | | |
| | | export interface ProcessInfoProps { |
| | | process: process |
| | | } |
| | |
| | | .font_weight { |
| | | font-weight: 600; |
| | | } |
| | | .process-info { |
| | | .craft-info { |
| | | width: calc(50% - 35px); |
| | | height: 110px; |
| | | padding: 23px 10px 10px; |
New file |
| | |
| | | <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% 生产中则从plc获取 |
| | | */ |
| | | 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> |
| | |
| | | <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"> |
| | |
| | | <template> |
| | | <DashboardLayout> |
| | | <template #leftBlock1> |
| | | <TaskTabs v-model="activeTaskTab" style="margin-top: 20px" :list="taskTabsTitle"></TaskTabs> |
| | | <TaskTabs v-model="activeTaskTab" style="margin-top: 20px" :list="taskTabsList" @change="changeTab"></TaskTabs> |
| | | </template> |
| | | <template #leftBlock2> |
| | | <ChannelCollapse :channels="channels"></ChannelCollapse> |
| | | </template> |
| | | <template #middleBlock1>标题</template> |
| | | <template #middleBlock2 |
| | | >主看板 |
| | | <ProcessInfo :process="process"></ProcessInfo> |
| | | <div v-if="activeTask"> |
| | | 任务详情 |
| | | {{ activeTask.Order.workOrderId }} |
| | | </div> |
| | | <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="工艺信息">Config</el-tab-pane> |
| | | <el-tab-pane label="物料清单" name="物料清单">Role</el-tab-pane> |
| | | </el-tabs> |
| | | </template> |
| | | <template #middleBlock3> 任务详情 </template> |
| | | <template #middleBlock4 |
| | |
| | | </DashboardLayout> |
| | | </template> |
| | | <script setup lang="ts"> |
| | | import { getTaskList } from '@/api' |
| | | import { computed, ref, watchEffect } from 'vue' |
| | | import { computed, ref } from 'vue' |
| | | import ChannelCollapse from '@/views/dashboard/components/ChannelCollapse.vue' |
| | | import type { Task, Worker } from '@/api/task' |
| | | import { chain } from 'lodash-es' |
| | | import ProcessInfo from '@/views/dashboard/components/ProcessInfo.vue' |
| | | import type { Worker } from '@/api/task' |
| | | import PersonInfo from '@/views/dashboard/components/PersonInfo.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' |
| | | |
| | | 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' |
| | | } as unknown as Worker |
| | | }) |
| | | getChannels() |
| | | const taskTabsTitle = ['未完成', '今日任务', '已完成'] |
| | | const activeTaskTab = ref('未完成') |
| | | 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) |
| | | |
| | | const { activeTask } = storeToRefs(tasksStore) |
| | | |
| | | watchEffect(() => { |
| | | // console.log(activeTaskTab?.value, 111111) |
| | | }) |
| | | function changeTab(tab: LabelValue) { |
| | | tasksStore.getChannels(tab.value) |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | <style scoped lang="scss"> |
| | | $active-tab-color: #00dfdf; |
| | | .date-time { |
| | | width: 100%; |
| | | display: flex; |
| | |
| | | justify-content: center; |
| | | padding-top: 12px; |
| | | } |
| | | |
| | | :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; |
| | | } |
| | | </style> |
| | |
| | | server: { |
| | | proxy: { |
| | | '/v1/': { |
| | | target: 'http://192.168.20.4:8003', |
| | | target: 'http://192.168.20.119:8003', |
| | | ws: true, |
| | | changeOrigin: true |
| | | } |