From 8ab349b4e271a068b67ad767587e23685760bd12 Mon Sep 17 00:00:00 2001
From: zhangwencui <1064582902@qq.com>
Date: 星期二, 17 三月 2026 11:34:57 +0800
Subject: [PATCH] 销售统计看板和生产统计看板页面设计
---
src/views/productionManagement/processRoute/index.vue | 2565 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 2,394 insertions(+), 171 deletions(-)
diff --git a/src/views/productionManagement/processRoute/index.vue b/src/views/productionManagement/processRoute/index.vue
index 7d5ab5d..40ab129 100644
--- a/src/views/productionManagement/processRoute/index.vue
+++ b/src/views/productionManagement/processRoute/index.vue
@@ -1,194 +1,2417 @@
<template>
<div class="app-container">
- <div class="search_form">
- <el-form :model="searchForm" :inline="true">
- <el-form-item label="瑙勬牸鍚嶇О:">
- <el-input v-model="searchForm.model" placeholder="璇疯緭鍏�" clearable prefix-icon="Search"
- style="width: 200px;"
- @change="handleQuery" />
+ <div class="route-header">
+ <div class="add-route-btn"
+ @click="handleAddRoute">
+ <el-icon>
+ <Plus />
+ </el-icon>
+ <span>鏂板宸ヨ壓璺嚎</span>
+ </div>
+ </div>
+ <div class="route-card-list">
+ <div v-for="route in routeList"
+ :key="route.id"
+ class="route-card">
+ <div class="card-header">
+ <div class="route-info">
+ <span class="route-name"><el-icon style="margin-right: 8px;line-height: 30px;">
+ <ScaleToOriginal />
+ </el-icon>{{route.routeCode }}<el-tag style="margin-left: 8px"
+ :type="!route.status ? 'warning' : 'success'">{{ !route.status ? '鑽夌' : '鎵瑰噯' }}</el-tag></span>
+ <!-- <span class="route-code">{{ route.routeCode }}</span> -->
+ </div>
+ <div class="route-actions">
+ <el-button v-if="!route.status"
+ link
+ type="success"
+ @click="handleApproveRoute(route)">
+ <el-icon>
+ <Check />
+ </el-icon>
+ 鎵瑰噯
+ </el-button>
+ <el-button v-if="route.status"
+ link
+ type="warning"
+ @click="handleRevokeApproveRoute(route)">
+ <el-icon>
+ <Close />
+ </el-icon>
+ 鎾ら攢鎵瑰噯
+ </el-button>
+ <el-button link
+ type="primary"
+ @click="handleEditRoute(route)">
+ <el-icon>
+ <Edit />
+ </el-icon>
+ 缂栬緫
+ </el-button>
+ <el-button link
+ type="danger"
+ @click="handleDeleteRoute(route)">
+ <el-icon>
+ <Delete />
+ </el-icon>
+ 鍒犻櫎
+ </el-button>
+ </div>
+ </div>
+ <div class="card-body">
+ <div class="route-meta">
+ <span class="meta-item">
+ <el-icon>
+ <Box />
+ </el-icon>
+ <span class="meta-label">浜у搧:</span>
+ <span class="meta-value">{{ route.productName }} - {{ route.productModelName }}</span>
+ </span>
+ <span class="meta-item">
+ <el-icon>
+ <Document />
+ </el-icon>
+ <span class="meta-label">BOM:</span>
+ <span class="meta-value">{{ route.bomNo || '-' }}</span>
+ </span>
+ <span class="meta-item">
+ <el-icon>
+ <Document />
+ </el-icon>
+ <span class="meta-label">澶囨敞:</span>
+ <span class="meta-value">{{ route.description || '鏆傛棤鎻忚堪' }}</span>
+ </span>
+ </div>
+ <div class="expand-btn-wrapper">
+ <el-button class="expand-btn"
+ :class="{ expanded: route.expanded }"
+ type="primary"
+ text
+ @click="toggleExpand(route)">
+ <span class="btn-text">{{ route.expanded ? '鏀惰捣宸ュ簭璺嚎' : '灞曞紑宸ュ簭璺嚎' }}</span>
+ <el-icon class="expand-icon">
+ <component :is="route.expanded ? 'ArrowUp' : 'ArrowDown'" />
+ </el-icon>
+ </el-button>
+ </div>
+ </div>
+ <div v-if="route.expanded"
+ class="process-route">
+ <div class="process-flow">
+ <div v-for="(process, index) in route.processList"
+ :key="process.id"
+ class="process-flow-item"
+ draggable="true"
+ @dragstart="handleDragStart($event, index, route.id)"
+ @dragover="handleDragOver($event)"
+ @drop="handleDrop($event, index, route.id)"
+ @dragend="handleDragEnd">
+ <div class="process-node"
+ :class="{ expanded: process.expanded }">
+ <div class="process-node-header">
+ <div class="process-number">{{ index + 1 }}</div>
+ <div class="process-actions">
+ <el-button link
+ type="primary"
+ @click="handleEditProcessSelect(route, index, process)">
+ <el-icon>
+ <Edit />
+ </el-icon>
+ </el-button>
+ <el-button link
+ type="danger"
+ @click="handleDeleteProcess(route.id, process)">
+ <el-icon>
+ <Delete />
+ </el-icon>
+ </el-button>
+ </div>
+ </div>
+ <div class="process-node-body">
+ <!-- <div class="process-code">{{ process.processId }}</div> -->
+ <div class="process-name">{{ process.processName }}</div>
+ <!-- <div class="process-desc">{{ process.remark || '鏆傛棤鎻忚堪' }}</div> -->
+ </div>
+ <div class="process-node-footer">
+ <!-- <el-tag size="small"
+ :type="process.status === '1' ? 'success' : 'info'">
+ {{ process.status === '1' ? '鍚敤' : '鍋滅敤' }}
+ </el-tag> -->
+ <el-button type="primary"
+ link
+ size="small"
+ @click="toggleProcessParams(process)">
+ {{ process.expanded ? '鏀惰捣鍙傛暟' : '灞曞紑鍙傛暟' }}
+ ({{ process.paramCount }})
+ </el-button>
+ </div>
+ <div v-if="process.expanded"
+ class="process-params-section">
+ <div class="params-header">
+ <span>鍙傛暟鍒楄〃</span>
+ <el-button type="primary"
+ link
+ size="small"
+ @click="handleAddParam(route.id, process)">
+ <el-icon>
+ <Plus />
+ </el-icon>鏂板
+ </el-button>
+ </div>
+ <div class="params-list">
+ <div v-for="param in process.paramList"
+ :key="param.id"
+ class="param-item">
+ <div class="param-info">
+ <span class="param-code">{{ param.paramName }}</span>
+ <!-- <span class="param-name">{{ param.paramName }}</span> -->
+ <!-- <el-tag size="small"
+ style="margin-right: 20px;"
+ :type="getParamTypeTag(param.parameterType)">
+ {{ param.parameterType }}
+ </el-tag> -->
+ <span v-if="param.valueMode==1"
+ class="param-value">鏍囧噯鍊硷細{{ param.standardValue || "-" }} {{ param.unit }}</span>
+ <span v-else
+ class="param-value">鏍囧噯鍊硷細{{ param.minValue || "-" }}-{{ param.maxValue || "-" }} {{ param.unit }}</span>
+ </div>
+ <div class="param-actions">
+ <el-button link
+ type="primary"
+ size="small"
+ @click="handleEditParam(route.id, process, param)">
+ 缂栬緫
+ </el-button>
+ <el-button link
+ type="danger"
+ size="small"
+ @click="handleDeleteParam(route.id, process, param)">
+ 鍒犻櫎
+ </el-button>
+ </div>
+ </div>
+ <el-empty v-if="!process.paramList || process.paramList.length === 0"
+ description="鏆傛棤鍙傛暟"
+ :image-size="50" />
+ </div>
+ </div>
+ </div>
+ <div v-if="index < route.processList.length - 1"
+ class="flow-arrow">
+ <el-icon>
+ <Right />
+ </el-icon>
+ </div>
+ </div>
+ <div class="add-process-node"
+ @click="handleSelectProcess(route, index)">
+ <el-icon>
+ <Plus />
+ </el-icon>
+ <span>鏂板宸ュ簭</span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <!-- 鍒嗛〉鎺т欢 -->
+ <div class="pagination-container">
+ <el-pagination v-model:current-page="routePage.current"
+ v-model:page-size="routePage.size"
+ :page-sizes="[10, 20, 50, 100]"
+ layout="total, sizes, prev, pager, next, jumper"
+ :total="routePage.total"
+ @size-change="handleRouteSizeChange"
+ @current-change="handleRouteCurrentChange" />
+ </div>
+ <!-- 宸ヨ壓璺嚎鏂板/缂栬緫瀵硅瘽妗� -->
+ <el-dialog v-model="routeDialogVisible"
+ :title="isRouteEdit ? '缂栬緫宸ヨ壓璺嚎' : '鏂板宸ヨ壓璺嚎'"
+ width="500px">
+ <el-form :model="routeForm"
+ :rules="routeRules"
+ ref="routeFormRef"
+ label-width="120px">
+ <el-form-item label="浜у搧鍚嶇О"
+ prop="productModelId">
+ <el-button type="primary"
+ @click="handleProcessProductSelectClick2">
+ {{ routeForm.productName && routeForm.productModelName
+ ? `${routeForm.productName} - ${routeForm.productModelName}`
+ : '閫夋嫨浜у搧' }}
+ </el-button>
</el-form-item>
- <el-form-item>
- <el-button type="primary" @click="handleQuery">鎼滅储</el-button>
+ <el-form-item label="BOM"
+ prop="bomId">
+ <el-select v-model="routeForm.bomId"
+ placeholder="璇烽�夋嫨BOM"
+ clearable
+ :disabled="!routeForm.productModelId || bomOptions.length === 0"
+ style="width: 100%">
+ <el-option v-for="item in bomOptions"
+ :key="item.id"
+ :label="item.bomNo || `BOM-${item.id}`"
+ :value="item.id" />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="璺嚎缂栫爜"
+ prop="routeCode">
+ <el-input v-model="routeForm.routeCode"
+ disabled
+ placeholder="鑷姩鐢熸垚" />
+ </el-form-item>
+ <el-form-item label="澶囨敞"
+ prop="description">
+ <el-input v-model="routeForm.description"
+ type="textarea"
+ :rows="3"
+ placeholder="璇疯緭鍏ヨ矾绾挎弿杩�" />
+ </el-form-item>
+ <!-- <el-form-item label="鐘舵��"
+ prop="status">
+ <el-radio-group v-model="routeForm.status">
+ <el-radio label="1">鍚敤</el-radio>
+ <el-radio label="0">鍋滅敤</el-radio>
+ </el-radio-group>
+ </el-form-item> -->
+ </el-form>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="routeDialogVisible = false">鍙栨秷</el-button>
+ <el-button type="primary"
+ @click="handleRouteSubmit">纭畾</el-button>
+ </span>
+ </template>
+ </el-dialog>
+ <!-- 浜у搧閫夋嫨寮圭獥 -->
+ <ProductSelectDialog v-model="showProductSelectDialog"
+ @confirm="handleProductSelect"
+ single />
+ <!-- 宸ュ簭鏂板/缂栬緫瀵硅瘽妗� -->
+ <el-dialog v-model="processDialogVisible"
+ :title="isProcessEdit ? '缂栬緫宸ュ簭' : '鏂板宸ュ簭'"
+ width="500px">
+ <el-form :model="processForm"
+ :rules="processRules"
+ ref="processFormRef"
+ label-width="120px">
+ <el-form-item label="宸ュ簭缂栫爜"
+ prop="no">
+ <el-input v-model="processForm.no"
+ placeholder="璇疯緭鍏ュ伐搴忕紪鐮�" />
+ </el-form-item>
+ <el-form-item label="宸ュ簭鍚嶇О"
+ prop="name">
+ <el-input v-model="processForm.name"
+ placeholder="璇疯緭鍏ュ伐搴忓悕绉�" />
+ </el-form-item>
+ <el-form-item label="宸ュ簭鎻忚堪"
+ prop="remark">
+ <el-input v-model="processForm.remark"
+ type="textarea"
+ :rows="3"
+ placeholder="璇疯緭鍏ュ伐搴忔弿杩�" />
+ </el-form-item>
+ <el-form-item label="鐘舵��"
+ prop="status">
+ <el-radio-group v-model="processForm.status">
+ <el-radio :label="true">鍚敤</el-radio>
+ <el-radio :label="false">鍋滅敤</el-radio>
+ </el-radio-group>
</el-form-item>
</el-form>
- </div>
- <div class="table_list">
- <div style="text-align: right" class="mb10">
- <el-button type="primary" @click="showNewModal">鏂板宸ヨ壓璺嚎</el-button>
- <el-button type="danger" @click="handleDelete" :disabled="selectedRows.length === 0" plain>鍒犻櫎宸ヨ壓璺嚎</el-button>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="processDialogVisible = false">鍙栨秷</el-button>
+ <el-button type="primary"
+ @click="handleProcessSubmit">纭畾</el-button>
+ </span>
+ </template>
+ </el-dialog>
+ <!-- 閫夋嫨宸ュ簭瀵硅瘽妗� -->
+ <el-dialog v-model="selectProcessDialogVisible"
+ title="閫夋嫨宸ュ簭"
+ width="1000px">
+ <div class="process-select-container">
+ <!-- 宸︿晶宸ュ簭鍒楄〃 -->
+ <div class="process-list-area">
+ <div class="area-title">鍙�夊伐搴�</div>
+ <div class="search-box">
+ <el-input v-model="processSearchKeyword"
+ placeholder="璇疯緭鍏ュ伐搴忓悕绉版悳绱�"
+ clearable
+ size="small"
+ @input="handleProcessSearch">
+ <template #prefix>
+ <el-icon>
+ <Search />
+ </el-icon>
+ </template>
+ </el-input>
+ </div>
+ <el-table :data="filteredProcessList"
+ height="360"
+ border
+ highlight-current-row
+ @current-change="handleProcessSelect">
+ <el-table-column prop="no"
+ label="宸ュ簭缂栧彿"
+ width="100" />
+ <el-table-column prop="name"
+ label="宸ュ簭鍚嶇О" />
+ <el-table-column prop="remark"
+ label="宸ュ簭鎻忚堪" />
+ <el-table-column prop="status"
+ label="鐘舵��"
+ width="80">
+ <template #default="scope">
+ <el-tag size="small"
+ :type="scope.row.status ? 'success' : 'info'">
+ {{ scope.row.status ? '鍚敤' : '鍋滅敤' }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ </el-table>
+ </div>
+ <!-- 鍙充晶宸ュ簭璇︽儏 -->
+ <div class="process-detail-area">
+ <div class="area-title">宸ュ簭璇︽儏</div>
+ <el-form v-if="selectedProcessItem"
+ :model="processForm"
+ label-width="100px"
+ class="process-detail-form">
+ <el-form-item label="宸ュ簭缂栧彿">
+ <span class="detail-text">{{ selectedProcessItem.no }}</span>
+ </el-form-item>
+ <el-form-item label="宸ュ簭鍚嶇О">
+ <span class="detail-text">{{ selectedProcessItem.name }}</span>
+ </el-form-item>
+ <el-form-item label="宸ュ簭鎻忚堪">
+ <span class="detail-text">{{ selectedProcessItem.remark || '-' }}</span>
+ </el-form-item>
+ <el-form-item label="鐘舵��">
+ <el-tag size="small"
+ :type="selectedProcessItem.status ? 'success' : 'info'">
+ {{ selectedProcessItem.status ? '鍚敤' : '鍋滅敤' }}
+ </el-tag>
+ </el-form-item>
+ <el-form-item label="鏄惁璐ㄦ">
+ <el-tag size="small"
+ :type="selectedProcessItem.isQuality ? 'success' : 'info'">
+ {{ selectedProcessItem.isQuality ? '璐ㄦ' : '闈炶川妫�' }}
+ </el-tag>
+ </el-form-item>
+ <el-form-item label="浜у搧鍚嶇О"
+ prop="productModelId">
+ <el-button type="primary"
+ @click="handleProcessProductSelectClick">
+ {{ processForm.productName && processForm.model
+ ? `${processForm.productName} - ${processForm.model}`
+ : '閫夋嫨浜у搧' }}
+ </el-button>
+ </el-form-item>
+ <el-form-item label="鍗曚綅"
+ prop="unit">
+ <el-input v-model="processForm.unit"
+ :placeholder="processForm.productModelId ? '鏍规嵁閫夋嫨鐨勪骇鍝佽嚜鍔ㄥ甫鍑�' : '璇峰厛閫夋嫨浜у搧' "
+ clearable
+ :disabled="true" />
+ </el-form-item>
+ <el-form-item label="鏄惁璐ㄦ"
+ prop="isQuality">
+ <el-switch v-model="processForm.isQuality"
+ :active-value="true"
+ inactive-value="false" />
+ </el-form-item>
+ </el-form>
+ <el-empty v-else
+ description="璇蜂粠宸︿晶閫夋嫨宸ュ簭" />
+ </div>
</div>
- <PIMTable
- rowKey="id"
- :column="tableColumn"
- :tableData="tableData"
- :page="page"
- :isSelection="true"
- @selection-change="handleSelectionChange"
- :tableLoading="tableLoading"
- @pagination="pagination"
- :total="page.total"
- />
- </div>
- <new-process
- v-if="isShowNewModal"
- v-model:visible="isShowNewModal"
- @completed="getList"
- />
-
- <edit-process
- v-if="isShowEditModal"
- v-model:visible="isShowEditModal"
- :record="record"
- @completed="getList"
- />
-
- <route-item-form
- v-if="isShowItemModal"
- v-model:visible="isShowItemModal"
- :record="record"
- @completed="getList"
- />
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="selectProcessDialogVisible = false">鍙栨秷</el-button>
+ <el-button type="primary"
+ :disabled="!selectedProcessItem || !processForm.productModelId"
+ @click="handleProcessSelectSubmit">纭畾</el-button>
+ </span>
+ </template>
+ </el-dialog>
+ <!-- 鍙傛暟鏂板/缂栬緫瀵硅瘽妗� -->
+ <el-dialog v-model="paramDialogVisible"
+ :title="isParamEdit ? '缂栬緫鍙傛暟' : '鏂板鍙傛暟'"
+ width="500px">
+ <el-form :model="paramForm"
+ :rules="paramRules"
+ ref="paramFormRef"
+ label-width="120px">
+ <el-form-item label="鍙傛暟缂栧彿"
+ prop="parameterCode">
+ <el-input v-model="paramForm.parameterCode"
+ placeholder="璇疯緭鍏ュ弬鏁扮紪鍙�" />
+ </el-form-item>
+ <el-form-item label="鍙傛暟鍚嶇О"
+ prop="parameterName">
+ <el-input v-model="paramForm.parameterName"
+ placeholder="璇疯緭鍏ュ弬鏁板悕绉�" />
+ </el-form-item>
+ <el-form-item label="鍙傛暟妯″紡"
+ prop="parameterType2">
+ <el-select v-model="paramForm.parameterType2"
+ placeholder="璇烽�夋嫨鍙傛暟妯″紡">
+ <el-option label="鍗曞��"
+ value="1" />
+ <el-option label="鍖洪棿"
+ value="2" />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="鍙傛暟绫诲瀷"
+ prop="parameterType">
+ <el-select v-model="paramForm.parameterType"
+ @change="handleParamTypeChange"
+ placeholder="璇烽�夋嫨鍙傛暟绫诲瀷">
+ <el-option label="鏁板�兼牸寮�"
+ value="鏁板�兼牸寮�" />
+ <el-option label="鏂囨湰鏍煎紡"
+ value="鏂囨湰鏍煎紡" />
+ <el-option label="涓嬫媺閫夐」"
+ value="涓嬫媺閫夐」" />
+ <el-option label="鏃堕棿鏍煎紡"
+ value="鏃堕棿鏍煎紡" />
+ </el-select>
+ </el-form-item>
+ <el-form-item v-if="paramForm.parameterType === '涓嬫媺閫夐」'"
+ label="鏁版嵁瀛楀吀"
+ prop="parameterFormat">
+ <el-select v-model="paramForm.parameterFormat"
+ placeholder="璇烽�夋嫨鏁版嵁瀛楀吀">
+ <el-option v-for="item in dictTypes"
+ :key="item.dictType"
+ :label="item.dictName"
+ :value="item.dictType" />
+ </el-select>
+ </el-form-item>
+ <el-form-item v-else-if="paramForm.parameterType === '鏃堕棿鏍煎紡'"
+ label="鏃堕棿鏍煎紡"
+ prop="parameterFormat">
+ <el-select v-model="paramForm.parameterFormat"
+ placeholder="璇烽�夋嫨鏃堕棿鏍煎紡">
+ <el-option label="YYYY-MM-DD HH:mm:ss"
+ value="YYYY-MM-DD HH:mm:ss" />
+ <el-option label="YYYY-MM-DD"
+ value="YYYY-MM-DD" />
+ </el-select>
+ </el-form-item>
+ <el-form-item v-else
+ label="鍙傛暟鏍煎紡"
+ prop="parameterFormat">
+ <el-input v-model="paramForm.parameterFormat"
+ placeholder="璇疯緭鍏ュ弬鏁版牸寮�" />
+ </el-form-item>
+ <el-form-item label="鏍囧噯鍊�"
+ prop="standardValue">
+ <el-input v-model="paramForm.standardValue"
+ placeholder="璇疯緭鍏ユ爣鍑嗗��" />
+ </el-form-item>
+ <el-form-item label="鍗曚綅"
+ prop="unit">
+ <el-input v-model="paramForm.unit"
+ placeholder="璇疯緭鍏ュ崟浣�" />
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="paramDialogVisible = false">鍙栨秷</el-button>
+ <el-button type="primary"
+ @click="handleParamSubmit">纭畾</el-button>
+ </span>
+ </template>
+ </el-dialog>
+ <!-- 閫夋嫨鍙傛暟瀵硅瘽妗� -->
+ <el-dialog v-model="selectParamDialogVisible"
+ title="閫夋嫨鍙傛暟"
+ width="1000px">
+ <div class="param-select-container">
+ <!-- 宸︿晶鍙傛暟鍒楄〃 -->
+ <div class="param-list-area">
+ <div class="area-title">鍙�夊弬鏁�</div>
+ <div class="search-box">
+ <el-input v-model="paramSearchKeyword"
+ placeholder="璇疯緭鍏ュ弬鏁板悕绉版悳绱�"
+ clearable
+ size="small"
+ @input="handleParamSearch">
+ <template #prefix>
+ <el-icon>
+ <Search />
+ </el-icon>
+ </template>
+ </el-input>
+ </div>
+ <el-table :data="filteredParamList"
+ height="300"
+ border
+ highlight-current-row
+ @current-change="handleParamSelect">
+ <el-table-column prop="paramName"
+ label="鍙傛暟鍚嶇О" />
+ <el-table-column prop="paramType"
+ label="鍙傛暟绫诲瀷">
+ <template #default="scope">
+ <el-tag size="small"
+ :type="getParamTypeTag(scope.row.paramType)">
+ {{ getParamTypeText(scope.row.paramType) }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ </el-table>
+ <!-- 鍒嗛〉鎺т欢 -->
+ <div class="pagination-container"
+ style="margin-top: 10px;">
+ <el-pagination v-model:current-page="paramPage.current"
+ v-model:page-size="paramPage.size"
+ :page-sizes="[10, 20, 50, 100]"
+ layout="total, sizes, prev, pager, next, jumper"
+ :total="paramPage.total"
+ @size-change="handleParamSizeChange"
+ @current-change="handleParamCurrentChange"
+ size="small" />
+ </div>
+ </div>
+ <!-- 鍙充晶鍙傛暟璇︽儏 -->
+ <div class="param-detail-area">
+ <div class="area-title">鍙傛暟璇︽儏</div>
+ <el-form v-if="selectedParam"
+ :model="selectedParam"
+ label-width="100px"
+ class="param-detail-form">
+ <el-form-item label="鍙傛暟鍚嶇О">
+ <span class="detail-text">{{ selectedParam.paramName }}</span>
+ </el-form-item>
+ <el-form-item label="鍙傛暟妯″紡">
+ <el-tag size="small"
+ :type="selectedParam.valueMode == '1' ? 'success' : 'warning'">
+ {{ selectedParam.valueMode == '1' ? '鍗曞��' : '鍖洪棿' }}
+ </el-tag>
+ </el-form-item>
+ <el-form-item label="鍙傛暟绫诲瀷">
+ <el-tag size="small"
+ :type="getParamTypeTag(selectedParam.paramType)">
+ {{ getParamTypeText(selectedParam.paramType) }}
+ </el-tag>
+ </el-form-item>
+ <el-form-item label="鍙傛暟鏍煎紡">
+ <span class="detail-text">{{ selectedParam.paramFormat || '-' }}</span>
+ </el-form-item>
+ <el-form-item label="鍗曚綅">
+ <span class="detail-text">{{ selectedParam.unit || '-' }}</span>
+ </el-form-item>
+ <el-form-item label="鏍囧噯鍊�"
+ v-if="selectedParam.valueMode == '1' && selectedParam.paramType == '1'">
+ <el-input v-model="selectedParam.standardValue"
+ type="number"
+ placeholder="璇疯緭鍏ラ粯璁ゅ��" />
+ </el-form-item>
+ <el-form-item label="鏈�灏忓��"
+ v-if="selectedParam.valueMode == '2' && selectedParam.paramType == '1'">
+ <el-input v-model="selectedParam.minValue"
+ type="number"
+ placeholder="璇疯緭鍏ユ渶灏忓��" />
+ </el-form-item>
+ <el-form-item label="鏈�澶у��"
+ v-if="selectedParam.valueMode == '2' && selectedParam.paramType == '1'">
+ <el-input v-model="selectedParam.maxValue"
+ type="number"
+ placeholder="璇疯緭鍏ユ渶澶у��" />
+ </el-form-item>
+ <el-form-item label="鎺掑簭">
+ <el-input v-model="selectedParam.sort"
+ type="number"
+ placeholder="璇疯緭鍏ユ帓搴�" />
+ </el-form-item>
+ <el-form-item label="鏄惁蹇呭~">
+ <el-switch v-model="selectedParam.isRequired"
+ :active-value="1"
+ :inactive-value="0" />
+ </el-form-item>
+ </el-form>
+ <el-empty v-else
+ description="璇蜂粠宸︿晶閫夋嫨鍙傛暟" />
+ </div>
+ </div>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="selectParamDialogVisible = false">鍙栨秷</el-button>
+ <el-button type="primary"
+ :disabled="!selectedParam"
+ @click="handleParamSelectSubmit">纭畾</el-button>
+ </span>
+ </template>
+ </el-dialog>
+ <!-- 缂栬緫鍙傛暟瀵硅瘽妗� -->
+ <el-dialog v-model="editParamDialogVisible"
+ title="缂栬緫鍙傛暟"
+ width="600px">
+ <el-form :model="editParamForm"
+ :rules="editParamRules"
+ ref="editParamFormRef"
+ label-width="120px">
+ <el-form-item label="鍙傛暟鍚嶇О">
+ <span class="detail-text">{{ editParamForm.paramName }}</span>
+ </el-form-item>
+ <el-form-item label="鍙傛暟妯″紡">
+ <el-tag size="small"
+ :type="editParamForm.valueMode == '1' ? 'success' : 'warning'">
+ {{ editParamForm.valueMode == '1' ? '鍗曞��' : '鍖洪棿' }}
+ </el-tag>
+ </el-form-item>
+ <el-form-item label="鍙傛暟绫诲瀷">
+ <el-tag size="small"
+ :type="getParamTypeTag(editParamForm.paramType)">
+ {{ getParamTypeText(editParamForm.paramType) }}
+ </el-tag>
+ </el-form-item>
+ <el-form-item label="鍙傛暟鏍煎紡">
+ <span class="detail-text">{{ editParamForm.paramFormat || '-' }}</span>
+ </el-form-item>
+ <el-form-item label="鍗曚綅">
+ <span class="detail-text">{{ editParamForm.unit || '-' }}</span>
+ </el-form-item>
+ <el-form-item label="鏍囧噯鍊�"
+ v-if="editParamForm.valueMode == '1' && editParamForm.paramType == '1'"
+ prop="standardValue">
+ <el-input v-model="editParamForm.standardValue"
+ type="number"
+ placeholder="璇疯緭鍏ユ爣鍑嗗��" />
+ </el-form-item>
+ <el-form-item label="鏈�灏忓��"
+ v-if="editParamForm.valueMode == '2' && editParamForm.paramType == '1'"
+ prop="minValue">
+ <el-input v-model="editParamForm.minValue"
+ type="number"
+ placeholder="璇疯緭鍏ユ渶灏忓��" />
+ </el-form-item>
+ <el-form-item label="鏈�澶у��"
+ v-if="editParamForm.valueMode == '2' && editParamForm.paramType == '1'"
+ prop="maxValue">
+ <el-input v-model="editParamForm.maxValue"
+ type="number"
+ placeholder="璇疯緭鍏ユ渶澶у��" />
+ </el-form-item>
+ <el-form-item label="鎺掑簭"
+ prop="sort">
+ <el-input v-model="editParamForm.sort"
+ type="number"
+ placeholder="璇疯緭鍏ユ帓搴�" />
+ </el-form-item>
+ <el-form-item label="鏄惁蹇呭~"
+ prop="isRequired">
+ <el-switch v-model="editParamForm.isRequired"
+ :active-value="1"
+ :inactive-value="0" />
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="editParamDialogVisible = false">鍙栨秷</el-button>
+ <el-button type="primary"
+ @click="handleEditParamSubmit">纭畾</el-button>
+ </span>
+ </template>
+ </el-dialog>
</div>
</template>
<script setup>
-import {onMounted, ref} from "vue";
-import NewProcess from "@/views/productionManagement/processRoute/New.vue";
-import EditProcess from "@/views/productionManagement/processRoute/Edit.vue";
-import RouteItemForm from "@/views/productionManagement/processRoute/ItemsForm.vue";
-import {listPage, del} from "@/api/productionManagement/processRoute.js";
-import { useRouter } from 'vue-router'
+ import { ref, reactive, getCurrentInstance, onMounted } from "vue";
+ import { ElMessage, ElMessageBox } from "element-plus";
+ import {
+ Plus,
+ Edit,
+ Delete,
+ ArrowUp,
+ ArrowDown,
+ Right,
+ Search,
+ Check,
+ Close,
+ Box,
+ Document,
+ } from "@element-plus/icons-vue";
+ import { listType } from "@/api/system/dict/type";
+ import { getByModel } from "@/api/productionManagement/productBom.js";
+ import { add, update, del } from "@/api/productionManagement/processRoute.js";
+ import {
+ addOrUpdateProcessRouteItem,
+ batchDeleteProcessRouteItem,
+ sortProcessRouteItem,
+ findProcessRouteItemList,
+ getProcessParamList,
+ addProcessRouteItemParam,
+ editProcessRouteItemParam,
+ delProcessRouteItemParam,
+ } from "@/api/productionManagement/processRouteItem.js";
+ import { list as getProcessListApi } from "@/api/productionManagement/productionProcess.js";
+ import { getBaseParamList } from "@/api/basicData/parameterMaintenance.js";
+ import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
-const router = useRouter()
-const data = reactive({
- searchForm: {
- model: "",
- },
-});
-const { searchForm } = toRefs(data);
-const tableColumn = ref([
- {
- label: "宸ヨ壓璺嚎缂栧彿",
- prop: "processRouteCode",
- },
- {
- label: "浜у搧鍚嶇О",
- prop: "productName",
- },
- {
- label: "瑙勬牸鍚嶇О",
- prop: "model",
- },
- {
- label: "鎻忚堪",
- prop: "description",
- },
- {
- dataType: "action",
- label: "鎿嶄綔",
- align: "center",
- fixed: "right",
- width: 280,
- operation: [
+ // 宸ヨ壓璺嚎鍒楄〃
+ const routeList = ref([]);
+ const dictTypes = ref([]);
+
+ // 宸ヨ壓璺嚎鍒嗛〉
+ const routePage = reactive({
+ current: 1,
+ size: 10,
+ total: 0,
+ });
+
+ // 鑾峰彇鍏ㄥ眬瀹炰緥
+ const { proxy } = getCurrentInstance();
+
+ // 浜у搧閫夋嫨鍜孊OM鐩稿叧
+ const showProductSelectDialog = ref(false);
+ const bomOptions = ref([]);
+
+ // 宸ヨ壓璺嚎瀵硅瘽妗�
+ const routeDialogVisible = ref(false);
+ const isRouteEdit = ref(false);
+ const routeFormRef = ref(null);
+ const routeForm = reactive({
+ id: null,
+ productModelId: null,
+ productName: "",
+ productModelName: "",
+ bomId: null,
+ routeCode: "",
+ description: "",
+ status: true,
+ });
+ const routeRules = {
+ productModelId: [
+ { required: true, message: "璇烽�夋嫨浜у搧", trigger: "change" },
+ ],
+ bomId: [{ required: true, message: "璇烽�夋嫨BOM", trigger: "change" }],
+ };
+
+ // 宸ュ簭瀵硅瘽妗�
+ const processDialogVisible = ref(false);
+ const isProcessEdit = ref(false);
+ const processFormRef = ref(null);
+ const currentRouteId = ref(null);
+ const processForm = reactive({
+ id: null,
+ no: "",
+ name: "",
+ remark: "",
+ status: true,
+ });
+ const processRules = {
+ no: [{ required: true, message: "璇疯緭鍏ュ伐搴忕紪鐮�", trigger: "blur" }],
+ name: [{ required: true, message: "璇疯緭鍏ュ伐搴忓悕绉�", trigger: "blur" }],
+ };
+
+ // 閫夋嫨宸ュ簭瀵硅瘽妗�
+ const selectProcessDialogVisible = ref(false);
+ const availableProcessList = ref([]);
+ const filteredProcessList = ref([]);
+ const selectedProcessItem = ref(null);
+ const processSearchKeyword = ref("");
+ const currentRouteIndex = ref(null);
+
+ // 鍙傛暟瀵硅瘽妗�
+ const paramDialogVisible = ref(false);
+ const isParamEdit = ref(false);
+ const paramFormRef = ref(null);
+ const currentProcessId = ref(null);
+ const paramForm = reactive({
+ id: null,
+ parameterCode: "",
+ parameterName: "",
+ parameterType2: "1",
+ parameterType: "",
+ parameterFormat: "",
+ standardValue: "",
+ unit: "",
+ });
+ const paramRules = {
+ parameterCode: [
+ { required: true, message: "璇疯緭鍏ュ弬鏁扮紪鍙�", trigger: "blur" },
+ ],
+ parameterName: [
+ { required: true, message: "璇疯緭鍏ュ弬鏁板悕绉�", trigger: "blur" },
+ ],
+ parameterType: [
+ { required: true, message: "璇烽�夋嫨鍙傛暟绫诲瀷", trigger: "change" },
+ ],
+ };
+
+ // 閫夋嫨鍙傛暟瀵硅瘽妗�
+ const selectParamDialogVisible = ref(false);
+ const availableParamList = ref([]);
+ const filteredParamList = ref([]);
+ const selectedParam = ref(null);
+ const paramSearchKeyword = ref("");
+
+ // 鍙�夊弬鏁板垎椤�
+ const paramPage = reactive({
+ current: 1,
+ size: 10,
+ total: 0,
+ });
+
+ // 缂栬緫鍙傛暟瀵硅瘽妗�
+ const editParamDialogVisible = ref(false);
+ const editParamFormRef = ref(null);
+ const editParamForm = reactive({
+ id: null,
+ processId: null,
+ paramId: null,
+ paramName: "",
+ valueMode: "1",
+ standardValue: null,
+ minValue: null,
+ maxValue: null,
+ sort: 1,
+ isRequired: 0,
+ });
+ const editParamRules = reactive({
+ standardValue: [
{
- name: "缂栬緫",
- type: "text",
- clickFun: (row) => {
- showEditModal(row);
- }
+ required: true,
+ message: "璇疯緭鍏ユ爣鍑嗗��",
+ trigger: "blur",
+ validator: (rule, value, callback) => {
+ if (value === null || value === undefined || value === "") {
+ callback(new Error("璇疯緭鍏ユ爣鍑嗗��"));
+ } else {
+ callback();
+ }
+ },
},
+ ],
+ minValue: [
{
- name: "璺嚎椤圭洰",
- type: "text",
- clickFun: (row) => {
- showItemModal(row);
+ required: true,
+ message: "璇疯緭鍏ユ渶灏忓��",
+ trigger: "blur",
+ validator: (rule, value, callback) => {
+ if (value === null || value === undefined || value === "") {
+ callback(new Error("璇疯緭鍏ユ渶灏忓��"));
+ } else {
+ callback();
+ }
+ },
+ },
+ ],
+ maxValue: [
+ {
+ required: true,
+ message: "璇疯緭鍏ユ渶澶у��",
+ trigger: "blur",
+ validator: (rule, value, callback) => {
+ if (value === null || value === undefined || value === "") {
+ callback(new Error("璇疯緭鍏ユ渶澶у��"));
+ } else {
+ callback();
+ }
+ },
+ },
+ ],
+ sort: [
+ {
+ required: true,
+ message: "璇疯緭鍏ユ帓搴�",
+ trigger: "blur",
+ validator: (rule, value, callback) => {
+ if (value === null || value === undefined || value === "") {
+ callback(new Error("璇疯緭鍏ユ帓搴�"));
+ } else if (isNaN(value) || value < 1) {
+ callback(new Error("鎺掑簭蹇呴』鏄ぇ浜�0鐨勬暣鏁�"));
+ } else {
+ callback();
+ }
+ },
+ },
+ ],
+ });
+
+ // 鎷栨嫿鐩稿叧
+ const draggedItem = ref(null);
+ const draggedRouteId = ref(null);
+
+ // 鑾峰彇宸ヨ壓璺嚎鍒楄〃
+ const getRouteList = () => {
+ // 瀵煎叆 listPage 鏂规硶
+ import("@/api/productionManagement/processRoute.js").then(({ listPage }) => {
+ listPage({ pageNum: routePage.current, pageSize: routePage.size })
+ .then(res => {
+ // 澶勭悊杩斿洖鐨勬暟鎹紝鏄犲皠鍒伴〉闈㈤渶瑕佺殑鏍煎紡
+ routeList.value = (res.data?.records || []).map(item => ({
+ id: item.id,
+ productModelId: item.productModelId,
+ productName: item.productName,
+ productModelName: item.model || item.productModelName,
+ bomId: item.bomId,
+ bomNo: item.bomNo,
+ routeCode: item.processRouteCode || item.routeCode,
+ description: item.description || item.description,
+ status: item.status,
+ expanded: false,
+ processList: (item.processList || []).map(process => ({
+ ...process,
+ processId: process.processId || process.id,
+ expanded: false,
+ })),
+ }));
+ // 鏇存柊鍒嗛〉鎬绘暟
+ routePage.total = res.data?.total || 0;
+ })
+ .catch(err => {
+ console.error("鑾峰彇宸ヨ壓璺嚎鍒楄〃澶辫触锛�", err);
+ routeList.value = [];
+ routePage.total = 0;
+ });
+ });
+ };
+
+ // 灞曞紑/鏀惰捣宸ヨ壓璺嚎
+ const toggleExpand = route => {
+ route.expanded = !route.expanded;
+ if (route.expanded) {
+ // 璋冪敤鎺ュ彛鑾峰彇宸ュ簭鍒楄〃
+ findProcessRouteItemList({ routeId: route.id })
+ .then(res => {
+ route.processList = (res.data || []).map(process => ({
+ ...process,
+ processId: process.processId || process.id,
+ expanded: false,
+ }));
+ })
+ .catch(err => {
+ console.error("鑾峰彇宸ュ簭鍒楄〃澶辫触锛�", err);
+ route.processList = [];
+ });
+ }
+ };
+
+ // 灞曞紑/鏀惰捣宸ュ簭鍙傛暟
+ const toggleProcessParams = process => {
+ process.expanded = !process.expanded;
+ if (process.expanded && process.id) {
+ // 璋冪敤鎺ュ彛鑾峰彇鍙傛暟鍒楄〃
+ getProcessParamList({
+ routeItemId: process.id,
+ pageNum: 1,
+ pageSize: 1000,
+ })
+ .then(res => {
+ if (res.code === 200) {
+ process.paramList = res.data?.records || [];
+ process.paramCount = process.paramList.length;
+ } else {
+ ElMessage.error(res.msg || "鑾峰彇鍙傛暟鍒楄〃澶辫触");
+ process.paramList = [];
+ process.paramCount = 0;
+ }
+ })
+ .catch(err => {
+ console.error("鑾峰彇鍙傛暟鍒楄〃澶辫触锛�", err);
+ ElMessage.error("鑾峰彇鍙傛暟鍒楄〃澶辫触");
+ process.paramList = [];
+ process.paramCount = 0;
+ });
+ }
+ };
+ const toggleProcessParams2 = process => {
+ if (process.expanded && process.id) {
+ // 璋冪敤鎺ュ彛鑾峰彇鍙傛暟鍒楄〃
+ getProcessParamList({
+ routeItemId: process.id,
+ pageNum: 1,
+ pageSize: 1000,
+ })
+ .then(res => {
+ if (res.code === 200) {
+ process.paramList = res.data?.records || [];
+ process.paramCount = process.paramList.length;
+ } else {
+ ElMessage.error(res.msg || "鑾峰彇鍙傛暟鍒楄〃澶辫触");
+ process.paramList = [];
+ process.paramCount = 0;
+ }
+ })
+ .catch(err => {
+ console.error("鑾峰彇鍙傛暟鍒楄〃澶辫触锛�", err);
+ ElMessage.error("鑾峰彇鍙傛暟鍒楄〃澶辫触");
+ process.paramList = [];
+ process.paramCount = 0;
+ });
+ }
+ };
+ // 宸ヨ壓璺嚎鎿嶄綔
+ const handleAddRoute = () => {
+ isRouteEdit.value = false;
+ routeForm.id = null;
+ routeForm.productModelId = null;
+ routeForm.productName = "";
+ routeForm.productModelName = "";
+ routeForm.bomId = null;
+ routeForm.routeCode = "";
+ routeForm.description = "";
+ routeForm.status = false;
+ bomOptions.value = [];
+ routeDialogVisible.value = true;
+ };
+
+ const handleEditRoute = route => {
+ isRouteEdit.value = true;
+ routeForm.id = route.id;
+ routeForm.productModelId = route.productModelId;
+ routeForm.productName = route.productName;
+ routeForm.productModelName = route.productModelName;
+ routeForm.bomId = route.bomId;
+ routeForm.routeCode = route.routeCode;
+ routeForm.description = route.description;
+ routeForm.status = route.status;
+ routeDialogVisible.value = true;
+ };
+
+ const handleDeleteRoute = route => {
+ ElMessageBox.confirm("纭畾瑕佸垹闄よ宸ヨ壓璺嚎鍚楋紵", "鎻愮ず", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ }).then(() => {
+ del(route.id)
+ .then(res => {
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ getRouteList();
+ })
+ .catch(err => {
+ ElMessage.error("鍒犻櫎澶辫触");
+ });
+ });
+ };
+
+ const handleRouteSubmit = () => {
+ routeFormRef.value.validate(valid => {
+ if (valid) {
+ // 鏋勫缓鎻愪氦鏁版嵁
+ const submitData = {
+ ...routeForm,
+ // 娉ㄦ剰锛欰PI 鏈熸湜鐨勫瓧娈靛悕鍙兘涓庤〃鍗曞瓧娈靛悕涓嶅悓
+ productId: routeForm.productModelId,
+ productModelId: routeForm.productModelId,
+ description: routeForm.description,
+ };
+
+ if (isRouteEdit.value) {
+ // 缂栬緫鎿嶄綔
+ update(submitData)
+ .then(res => {
+ ElMessage.success("缂栬緫鎴愬姛");
+ routeDialogVisible.value = false;
+ getRouteList();
+ })
+ .catch(err => {
+ ElMessage.error("缂栬緫澶辫触");
+ });
+ } else {
+ // 鏂板鎿嶄綔
+ add(submitData)
+ .then(res => {
+ ElMessage.success("鏂板鎴愬姛");
+ routeDialogVisible.value = false;
+ getRouteList();
+ })
+ .catch(err => {
+ ElMessage.error("鏂板澶辫触");
+ });
}
}
- ]
- }
-]);
-const tableData = ref([]);
-const selectedRows = ref([]);
-const tableLoading = ref(false);
-const isShowNewModal = ref(false);
-const isShowEditModal = ref(false);
-const isShowItemModal = ref(false);
-const record = ref({});
-const page = reactive({
- current: 1,
- size: 100,
- total: 0,
-});
-const { proxy } = getCurrentInstance()
+ });
+ };
+ const isform2 = ref(null);
+ const handleProcessProductSelectClick = () => {
+ isform2.value = true;
+ showProductSelectDialog.value = true;
+ };
+ const handleProcessProductSelectClick2 = () => {
+ isform2.value = false;
+ showProductSelectDialog.value = true;
+ };
-// 鏌ヨ鍒楄〃
-/** 鎼滅储鎸夐挳鎿嶄綔 */
-const handleQuery = () => {
- page.current = 1;
- getList();
-};
+ // 浜у搧閫夋嫨澶勭悊
+ const handleProductSelect = async products => {
+ if (isform2.value) {
+ // 甯垜鍐欏伐搴忎腑鐨勯�夋嫨浜у搧鐨勫洖璋�,骞朵笖鎶婂瓧娈靛姞杩沺rocessForm
+ if (products && products.length > 0) {
+ const product = products[0];
+ console.log("product:", product);
+ // 鎶妏roduct涓殑瀛楁娣诲姞鍒皃rocessForm涓�
+ // Object.assign(processForm, product);
+ processForm.productModelId = product.id;
+ processForm.productName = product.productName;
+ processForm.model = product.model;
+ processForm.unit = product.unit || "";
+ console.log("processForm:", processForm);
-const pagination = (obj) => {
- page.current = obj.page;
- page.size = obj.limit;
- getList();
-};
-const getList = () => {
- tableLoading.value = true;
- const params = { ...searchForm.value, ...page };
- params.entryDate = undefined
- listPage(params).then(res => {
- tableLoading.value = false;
- tableData.value = res.data.records.map(item => ({
- ...item,
- }));
- page.total = res.data.total;
- }).catch(err => {
- tableLoading.value = false;
- })
-};
-// 琛ㄦ牸閫夋嫨鏁版嵁
-const handleSelectionChange = (selection) => {
- selectedRows.value = selection;
-};
-
-// 鎵撳紑鏂板寮规
-const showNewModal = () => {
- isShowNewModal.value = true
-};
-
-const showEditModal = (row) => {
- isShowEditModal.value = true
- record.value = row
-};
-
-const showItemModal = (row) => {
- router.push({
- path: '/productionManagement/processRouteItem',
- query: {
- id: row.id
+ // 瑙﹀彂琛ㄥ崟楠岃瘉鏇存柊
+ proxy.$refs["processFormRef"]?.validateField("productModelId");
+ }
+ } else {
+ if (products && products.length > 0) {
+ const product = products[0];
+ // 鍏堟煡璇OM鍒楄〃锛堝繀閫夛級
+ try {
+ const res = await getByModel(product.id);
+ // 澶勭悊杩斿洖鐨凚OM鏁版嵁锛氬彲鑳芥槸鏁扮粍銆佸璞℃垨鍖呭惈data瀛楁
+ let bomList = [];
+ if (Array.isArray(res)) {
+ bomList = res;
+ } else if (res && res.data) {
+ bomList = Array.isArray(res.data) ? res.data : [res.data];
+ } else if (res && typeof res === "object") {
+ bomList = [res];
+ }
+ console.log("bomList:", bomList);
+ if (bomList.length > 0) {
+ routeForm.productModelId = product.id;
+ routeForm.productName = product.productName;
+ routeForm.productModelName = product.model;
+ routeForm.bomId = undefined; // 閲嶇疆BOM閫夋嫨
+ bomOptions.value = bomList;
+ showProductSelectDialog.value = false;
+ // 瑙﹀彂琛ㄥ崟楠岃瘉鏇存柊
+ proxy.$refs["routeFormRef"]?.validateField("productModelId");
+ } else {
+ proxy.$modal.msgError("璇ヤ骇鍝佹病鏈塀OM锛岃鍏堝垱寤築OM");
+ }
+ } catch (error) {
+ // 濡傛灉鎺ュ彛杩斿洖404鎴栧叾浠栭敊璇紝璇存槑娌℃湁BOM
+ proxy.$modal.msgError("璇ヤ骇鍝佹病鏈塀OM锛岃鍏堝垱寤築OM");
+ }
+ }
}
- })
-};
+ };
-// 鍒犻櫎
-function handleDelete() {
- const ids = selectedRows.value.map((item) => item.id);
- proxy.$modal
- .confirm('鏄惁纭鍒犻櫎宸插嬀閫夌殑鏁版嵁椤癸紵')
- .then(function () {
- return del(ids);
- })
- .then(() => {
- getList();
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- })
- .catch(() => {});
-}
+ const handleApproveRoute = route => {
+ ElMessageBox.confirm("纭畾瑕佹壒鍑嗚宸ヨ壓璺嚎鍚楋紵", "鎻愮ず", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "info",
+ }).then(() => {
+ // 璋冪敤淇敼鎺ュ彛锛屽彧淇敼status瀛楁涓烘壒鍑嗙姸鎬�
+ update({ id: route.id, status: true })
+ .then(res => {
+ ElMessage.success("鎵瑰噯鎴愬姛");
+ getRouteList();
+ })
+ .catch(err => {
+ ElMessage.error("鎵瑰噯澶辫触");
+ });
+ });
+ };
-onMounted(() => {
- getList();
-});
+ const handleRevokeApproveRoute = route => {
+ ElMessageBox.confirm("纭畾瑕佹挙閿�鎵瑰噯璇ュ伐鑹鸿矾绾垮悧锛�", "鎻愮ず", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ }).then(() => {
+ // 璋冪敤淇敼鎺ュ彛锛屽彧淇敼status瀛楁涓鸿崏绋跨姸鎬�
+ update({ id: route.id, status: false })
+ .then(res => {
+ ElMessage.success("鎾ら攢鎵瑰噯鎴愬姛");
+ getRouteList();
+ })
+ .catch(err => {
+ ElMessage.error("鎾ら攢鎵瑰噯澶辫触");
+ });
+ });
+ };
+ // 宸ュ簭鎿嶄綔
+ const handleSelectProcess = (route, index) => {
+ console.log("route:", route);
+ currentRouteId.value = route.id;
+ currentRouteIndex.value = index;
+ // 閲嶇疆鎼滅储鍜岄�夋嫨鐘舵��
+ filteredProcessList.value = availableProcessList.value;
+ processSearchKeyword.value = "";
+ selectedProcessItem.value = null;
+ selectProcessDialogVisible.value = true;
+ };
+ const dragSort = ref(0);
+ const currentId = ref(null);
+ // 淇敼宸ュ簭
+ const handleEditProcessSelect = (route, index, process) => {
+ console.log("route:", route);
+ console.log("process:", process);
+ currentId.value = process.id;
+ currentRouteId.value = route.id;
+ currentRouteIndex.value = index;
+ // 閲嶇疆鎼滅储鍜岄�夋嫨鐘舵��
+ filteredProcessList.value = availableProcessList.value;
+ processSearchKeyword.value = "";
+ // 璁剧疆閫変腑鐨勫伐搴�
+ filteredProcessList.value.map(item => {
+ if (item.id === process.processId) {
+ selectedProcessItem.value = item;
+ }
+ });
+ dragSort.value = process.dragSort;
+ // selectedProcessItem.value = process;
+ // 濉厖浜у搧閫夋嫨琛ㄥ崟
+ processForm.productModelId = process.productModelId;
+ processForm.productName = process.productName;
+ processForm.model = process.model;
+ processForm.processId = process.no;
+ // processForm.name = process.name;
+ processForm.unit = process.unit || "";
+ processForm.isQuality = process.isQuality || false;
+ selectProcessDialogVisible.value = true;
+ };
+
+ const handleEditProcess = (routeId, process) => {
+ currentRouteId.value = routeId;
+ isProcessEdit.value = true;
+ processForm.id = process.id;
+ processForm.no = process.no;
+ processForm.name = process.name;
+ processForm.remark = process.remark;
+ processForm.status = process.status;
+ processDialogVisible.value = true;
+ };
+
+ const handleDeleteProcess = (routeId, process) => {
+ ElMessageBox.confirm("纭畾瑕佸垹闄よ宸ュ簭鍚楋紵", "鎻愮ず", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ }).then(() => {
+ // 璋冪敤API鍒犻櫎宸ュ簭
+ batchDeleteProcessRouteItem([process.id])
+ .then(res => {
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ // 璋冪敤鎺ュ彛鏇存柊宸ュ簭鍒楄〃
+ findProcessRouteItemList({ routeId: routeId })
+ .then(res => {
+ const route = routeList.value.find(r => r.id === routeId);
+ if (route) {
+ route.processList = (res.data || []).map(process => ({
+ ...process,
+ processId: process.processId || process.id,
+ expanded: false,
+ }));
+ }
+ })
+ .catch(err => {
+ console.error("鑾峰彇宸ュ簭鍒楄〃澶辫触锛�", err);
+ });
+ })
+ .catch(err => {
+ ElMessage.error("鍒犻櫎澶辫触");
+ console.error("鍒犻櫎宸ュ簭澶辫触锛�", err);
+ });
+ });
+ };
+
+ const handleProcessSubmit = () => {
+ processFormRef.value.validate(valid => {
+ if (valid) {
+ ElMessage.success(isProcessEdit.value ? "缂栬緫鎴愬姛" : "鏂板鎴愬姛");
+ processDialogVisible.value = false;
+ // 璋冪敤鎺ュ彛鏇存柊宸ュ簭鍒楄〃
+ if (currentRouteId.value) {
+ findProcessRouteItemList({ routeId: currentRouteId.value })
+ .then(res => {
+ const route = routeList.value.find(
+ r => r.id === currentRouteId.value
+ );
+ if (route) {
+ route.processList = (res.data || []).map(process => ({
+ ...process,
+ processId: process.processId || process.id,
+ expanded: false,
+ }));
+ }
+ })
+ .catch(err => {
+ console.error("鑾峰彇宸ュ簭鍒楄〃澶辫触锛�", err);
+ });
+ }
+ }
+ });
+ };
+
+ // 閫夋嫨宸ュ簭鐩稿叧鏂规硶
+ const handleProcessSearch = () => {
+ const keyword = processSearchKeyword.value.trim().toLowerCase();
+ if (!keyword) {
+ filteredProcessList.value = availableProcessList.value;
+ } else {
+ filteredProcessList.value = availableProcessList.value.filter(
+ item =>
+ (item.name && item.name.toLowerCase().includes(keyword)) ||
+ (item.no && item.no.toLowerCase().includes(keyword))
+ );
+ }
+ };
+
+ const handleProcessSelect = row => {
+ selectedProcessItem.value = row;
+ // 閲嶇疆浜у搧閫夋嫨琛ㄥ崟
+ processForm.productModelId = undefined;
+ processForm.productName = "";
+ processForm.productModelName = "";
+ processForm.unit = "";
+ processForm.isQuality = row.isQuality || false;
+ };
+
+ // 澶勭悊宸ュ簭閫夋嫨鏃剁殑浜у搧閫夋嫨
+ const handleProcessProductSelect = async products => {
+ if (products && products.length > 0) {
+ const product = products[0];
+ processForm.productModelId = product.id;
+ processForm.productName = product.productName;
+ processForm.productModelName = product.model;
+ processForm.unit = product.unit || "";
+ showProductSelectDialog.value = false;
+ }
+ };
+
+ const handleProcessSelectSubmit = () => {
+ if (!selectedProcessItem.value) {
+ ElMessage.warning("璇峰厛閫夋嫨涓�涓伐搴�");
+ return;
+ }
+
+ if (!processForm.productModelId) {
+ ElMessage.warning("璇烽�夋嫨浜у搧");
+ return;
+ }
+
+ // 鏋勫缓璇锋眰鍙傛暟
+ const params = {
+ routeId: currentRouteId.value,
+ processId: selectedProcessItem.value.id,
+ dragSort: routePage.total + 1,
+ ...processForm,
+ };
+
+ // 濡傛灉鏄慨鏀规搷浣滐紝娣诲姞id鍙傛暟
+ if (selectedProcessItem.value.id) {
+ params.id = currentId.value;
+ params.dragSort = dragSort.value;
+ }
+
+ // 璋冪敤API娣诲姞宸ュ簭鎴栦慨鏀瑰伐搴�
+ addOrUpdateProcessRouteItem(params)
+ .then(res => {
+ ElMessage.success(
+ selectedProcessItem.value.id ? "淇敼宸ュ簭鎴愬姛" : "娣诲姞宸ュ簭鎴愬姛"
+ );
+ selectProcessDialogVisible.value = false;
+ // 璋冪敤鎺ュ彛鏇存柊宸ュ簭鍒楄〃
+ findProcessRouteItemList({ routeId: currentRouteId.value })
+ .then(res => {
+ const route = routeList.value.find(
+ r => r.id === currentRouteId.value
+ );
+ if (route) {
+ route.processList = (res.data || []).map(process => ({
+ ...process,
+ processId: process.processId || process.id,
+ expanded: false,
+ }));
+ }
+ })
+ .catch(err => {
+ console.error("鑾峰彇宸ュ簭鍒楄〃澶辫触锛�", err);
+ });
+ })
+ .catch(err => {
+ ElMessage.error(
+ selectedProcessItem.value.id ? "淇敼宸ュ簭澶辫触" : "娣诲姞宸ュ簭澶辫触"
+ );
+ console.error(
+ selectedProcessItem.value.id ? "淇敼宸ュ簭澶辫触锛�" : "娣诲姞宸ュ簭澶辫触锛�",
+ err
+ );
+ });
+ };
+
+ // 鍙傛暟鎿嶄綔
+ const handleAddParam = (routeId, process) => {
+ currentRouteId.value = routeId;
+ currentProcessId.value = process.id;
+ selectedParam.value = null;
+ paramSearchKeyword.value = "";
+ paramPage.current = 1;
+ // 鑾峰彇鍙�夊弬鏁板垪琛�
+ getBaseParamList({
+ paramName: paramSearchKeyword.value,
+ current: paramPage.current,
+ size: paramPage.size,
+ }).then(res => {
+ if (res.code === 200) {
+ filteredParamList.value = res.data?.records || [];
+ paramPage.total = res.data?.total || 0;
+ } else {
+ ElMessage.error(res.msg || "鏌ヨ澶辫触");
+ }
+ });
+ selectParamDialogVisible.value = true;
+ };
+
+ const handleEditParam = (routeId, process, param) => {
+ currentRouteId.value = routeId;
+ currentProcessId.value = process.id;
+ editParamForm.id = param.id;
+ editParamForm.processId = process.id;
+ editParamForm.paramId = param.paramId;
+ editParamForm.paramName = param.parameterName || param.paramName;
+ editParamForm.valueMode = param.parameterType2 || param.valueMode || "1";
+ editParamForm.standardValue = param.standardValue;
+ editParamForm.minValue = param.minValue;
+ editParamForm.maxValue = param.maxValue;
+ editParamForm.sort = param.sort || 1;
+ editParamForm.isRequired = param.isRequired || 0;
+ editParamForm.paramType = param.parameterType || param.paramType;
+ editParamForm.paramFormat = param.parameterFormat || param.paramFormat;
+ editParamForm.unit = param.unit || param.unit;
+ editParamDialogVisible.value = true;
+ };
+
+ const handleDeleteParam = (routeId, process, param) => {
+ ElMessageBox.confirm("纭畾瑕佸垹闄よ鍙傛暟鍚楋紵", "鎻愮ず", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ }).then(() => {
+ // 璋冪敤API鍒犻櫎鍙傛暟
+ delProcessRouteItemParam(param.id)
+ .then(res => {
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ // 鍒锋柊鍙傛暟鍒楄〃
+ toggleProcessParams2(process);
+ })
+ .catch(err => {
+ ElMessage.error("鍒犻櫎鍙傛暟澶辫触");
+ console.error("鍒犻櫎鍙傛暟澶辫触锛�", err);
+ });
+ });
+ };
+
+ const handleParamSubmit = () => {
+ paramFormRef.value.validate(valid => {
+ if (valid) {
+ ElMessage.success(isParamEdit.value ? "缂栬緫鎴愬姛" : "鏂板鎴愬姛");
+ paramDialogVisible.value = false;
+ getRouteList();
+ }
+ });
+ };
+
+ const handleParamTypeChange = () => {
+ if (paramForm.parameterType === "鏁板�兼牸寮�") {
+ paramForm.parameterFormat = "#.0000";
+ } else if (paramForm.parameterType === "鏃堕棿鏍煎紡") {
+ paramForm.parameterFormat = "YYYY-MM-DD HH:mm:ss";
+ } else {
+ paramForm.parameterFormat = "";
+ }
+ };
+
+ const getParamTypeTag = type => {
+ const typeMap = {
+ 1: "primary",
+ 2: "info",
+ 3: "warning",
+ 4: "success",
+ };
+ return typeMap[type] || "default";
+ };
+
+ const getParamTypeText = type => {
+ const typeMap = {
+ 1: "鏁板�兼牸寮�",
+ 2: "鏂囨湰鏍煎紡",
+ 3: "涓嬫媺閫夐」",
+ 4: "鏃堕棿鏍煎紡",
+ };
+ return typeMap[type] || "鏈煡鍙傛暟绫诲瀷";
+ };
+
+ // 閫夋嫨鍙傛暟鐩稿叧鏂规硶
+ const handleParamSearch = () => {
+ // 閲嶇疆鍒嗛〉
+ paramPage.current = 1;
+ // 閲嶆柊鍔犺浇鏁版嵁
+ getBaseParamList({
+ paramName: paramSearchKeyword.value,
+ current: paramPage.current,
+ size: paramPage.size,
+ }).then(res => {
+ if (res.code === 200) {
+ filteredParamList.value = res.data?.records || [];
+ paramPage.total = res.data?.total || 0;
+ } else {
+ ElMessage.error(res.msg || "鏌ヨ澶辫触");
+ }
+ });
+ };
+
+ const handleParamSelect = row => {
+ selectedParam.value = row;
+ };
+
+ // 澶勭悊鍒嗛〉澶у皬鍙樺寲
+ const handleParamSizeChange = size => {
+ paramPage.size = size;
+ getBaseParamList({
+ paramName: paramSearchKeyword.value,
+ current: paramPage.current,
+ size: paramPage.size,
+ }).then(res => {
+ if (res.code === 200) {
+ filteredParamList.value = res.data?.records || [];
+ paramPage.total = res.data?.total || 0;
+ } else {
+ ElMessage.error(res.msg || "鏌ヨ澶辫触");
+ }
+ });
+ };
+
+ // 澶勭悊褰撳墠椤电爜鍙樺寲
+ const handleParamCurrentChange = current => {
+ paramPage.current = current;
+ getBaseParamList({
+ paramName: paramSearchKeyword.value,
+ current: paramPage.current,
+ size: paramPage.size,
+ }).then(res => {
+ if (res.code === 200) {
+ filteredParamList.value = res.data?.records || [];
+ paramPage.total = res.data?.total || 0;
+ } else {
+ ElMessage.error(res.msg || "鏌ヨ澶辫触");
+ }
+ });
+ };
+
+ // 宸ヨ壓璺嚎鍒嗛〉澶勭悊
+ const handleRouteSizeChange = size => {
+ routePage.size = size;
+ getRouteList();
+ };
+
+ const handleRouteCurrentChange = current => {
+ routePage.current = current;
+ getRouteList();
+ };
+
+ const handleParamSelectSubmit = () => {
+ if (!selectedParam.value) {
+ ElMessage.warning("璇峰厛閫夋嫨涓�涓弬鏁�");
+ return;
+ }
+
+ // 鎵惧埌瀵瑰簲鐨勫伐鑹鸿矾绾垮拰宸ュ簭
+ const route = routeList.value.find(r => r.id === currentRouteId.value);
+ const process = route?.processList.find(p => p.id === currentProcessId.value);
+
+ if (route && process) {
+ // 妫�鏌ュ弬鏁版槸鍚﹀凡瀛樺湪
+ // const exists = process.paramList?.some(
+ // p =>
+ // p.paramId === selectedParam.value.id ||
+ // p.parameterCode === selectedParam.value.paramCode
+ // );
+ // if (exists) {
+ // ElMessage.warning("璇ュ弬鏁板凡瀛樺湪浜庡伐搴忎腑");
+ // return;
+ // }
+
+ // 鍒ゆ柇鍙傛暟绫诲瀷锛屽彧鏈夋暟鍊肩被鍨嬫墠浼犳爣鍑嗗�笺�佹渶澶у�煎拰鏈�灏忓��
+ const isNumericMode = selectedParam.value.valueMode === 1;
+
+ // 璋冪敤API鏂板鍙傛暟
+ addProcessRouteItemParam({
+ routeItemId: process.id,
+ paramId: selectedParam.value.id,
+ standardValue: isNumericMode
+ ? selectedParam.value.standardValue || ""
+ : "",
+ minValue: isNumericMode ? selectedParam.value.minValue || 0 : null,
+ maxValue: isNumericMode ? selectedParam.value.maxValue || 0 : null,
+ isRequired: selectedParam.value.isRequired || 0,
+ })
+ .then(res => {
+ ElMessage.success("娣诲姞鍙傛暟鎴愬姛");
+ selectParamDialogVisible.value = false;
+ // 鍒锋柊鍙傛暟鍒楄〃
+ toggleProcessParams2(process);
+ })
+ .catch(err => {
+ ElMessage.error("娣诲姞鍙傛暟澶辫触");
+ console.error("娣诲姞鍙傛暟澶辫触锛�", err);
+ });
+ }
+ };
+
+ const handleEditParamSubmit = () => {
+ editParamFormRef.value.validate(valid => {
+ if (valid) {
+ // 鍒ゆ柇鍙傛暟绫诲瀷锛屽彧鏈夋暟鍊肩被鍨嬫墠浼犳爣鍑嗗�笺�佹渶澶у�煎拰鏈�灏忓��
+ const isNumericMode = editParamForm.valueMode == 1;
+
+ // 璋冪敤API淇敼鍙傛暟
+ editProcessRouteItemParam({
+ id: editParamForm.id,
+ routeItemId: currentProcessId.value,
+ paramId: editParamForm.paramId,
+ standardValue: isNumericMode ? editParamForm.standardValue || "" : "",
+ minValue: isNumericMode ? editParamForm.minValue || 0 : null,
+ maxValue: isNumericMode ? editParamForm.maxValue || 0 : null,
+ isRequired: editParamForm.isRequired || 0,
+ })
+ .then(res => {
+ ElMessage.success("缂栬緫鎴愬姛");
+ editParamDialogVisible.value = false;
+ // 鎵惧埌瀵瑰簲鐨勫伐鑹鸿矾绾垮拰宸ュ簭
+ const route = routeList.value.find(
+ r => r.id === currentRouteId.value
+ );
+ const process = route?.processList.find(
+ p => p.id === currentProcessId.value
+ );
+ // 鍒锋柊鍙傛暟鍒楄〃
+ if (process) {
+ toggleProcessParams2(process);
+ }
+ })
+ .catch(err => {
+ ElMessage.error("缂栬緫鍙傛暟澶辫触");
+ console.error("缂栬緫鍙傛暟澶辫触锛�", err);
+ });
+ }
+ });
+ };
+
+ // 鎷栨嫿鎺掑簭
+ const handleDragStart = (event, index, routeId) => {
+ draggedItem.value = index;
+ draggedRouteId.value = routeId;
+ event.dataTransfer.effectAllowed = "move";
+ };
+
+ const handleDragOver = event => {
+ event.preventDefault();
+ event.dataTransfer.dropEffect = "move";
+ };
+
+ const handleDrop = (event, dropIndex, routeId) => {
+ event.preventDefault();
+ if (draggedItem.value === null || draggedItem.value === dropIndex) return;
+
+ const route = routeList.value.find(r => r.id === routeId);
+ if (route && route.processList) {
+ const draggedProcess = route.processList[draggedItem.value];
+
+ // 璁$畻鏂扮殑鎺掑簭鍊�
+ const newDragSort = dropIndex + 1;
+
+ // 璋冪敤API鎺掑簭宸ュ簭
+ sortProcessRouteItem({
+ id: draggedProcess.id,
+ dragSort: newDragSort,
+ })
+ .then(res => {
+ // 璋冪敤鎺ュ彛鑾峰彇鏈�鏂扮殑宸ュ簭鍒楄〃
+ findProcessRouteItemList({ routeId: routeId })
+ .then(res => {
+ if (route) {
+ route.processList = (res.data || []).map(process => ({
+ ...process,
+ processId: process.processId || process.id,
+ expanded: false,
+ }));
+ }
+ ElMessage.success("鎺掑簭鎴愬姛");
+ })
+ .catch(err => {
+ console.error("鑾峰彇宸ュ簭鍒楄〃澶辫触锛�", err);
+ ElMessage.success("鎺掑簭鎴愬姛");
+ });
+ })
+ .catch(err => {
+ ElMessage.error("鎺掑簭澶辫触");
+ console.error("鎺掑簭宸ュ簭澶辫触锛�", err);
+ });
+ }
+ };
+
+ const handleDragEnd = () => {
+ draggedItem.value = null;
+ draggedRouteId.value = null;
+ };
+
+ // 鑾峰彇鏁版嵁瀛楀吀
+ const getDictTypes = () => {
+ listType({ pageNum: 1, pageSize: 1000 }).then(res => {
+ dictTypes.value = res.rows || [];
+ });
+ };
+
+ getRouteList();
+ getDictTypes();
+
+ // 椤甸潰鍔犺浇鏃惰幏鍙栧伐搴忓垪琛�
+ onMounted(() => {
+ getProcessListApi()
+ .then(res => {
+ // 澶勭悊杩斿洖鐨勬暟鎹紝鏄犲皠鍒伴〉闈㈤渶瑕佺殑鏍煎紡
+ availableProcessList.value = (res.data || []).map(item => ({
+ id: item.id,
+ no: item.no || item.no,
+ name: item.name || item.name,
+ remark: item.remark || item.remark,
+ status: item.status,
+ isQuality: item.isQuality,
+ }));
+ filteredProcessList.value = availableProcessList.value;
+ })
+ .catch(() => {
+ ElMessage.error("鑾峰彇宸ュ簭鍒楄〃澶辫触");
+ });
+ });
</script>
-<style scoped></style>
+<style scoped lang="scss">
+ .app-container {
+ padding: 20px;
+ padding-bottom: 80px;
+ background-color: #f0f2f5;
+ min-height: calc(100vh - 84px);
+ overflow: hidden;
+ }
+
+ .route-header {
+ margin-bottom: 20px;
+
+ .add-route-btn {
+ width: 100%;
+ display: inline-flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ min-width: 120px;
+ height: 100px;
+ border: 2px dashed #dcdfe6;
+ border-radius: 12px;
+ background: #fafafa;
+ cursor: pointer;
+ transition: all 0.3s ease;
+ color: #909399;
+ padding: 0 20px;
+
+ .el-icon {
+ font-size: 24px;
+ margin-bottom: 8px;
+ }
+
+ span {
+ font-size: 13px;
+ }
+
+ &:hover {
+ border-color: #409eff;
+ background: #ecf5ff;
+ color: #409eff;
+ }
+ }
+ }
+
+ .route-card-list {
+ display: grid;
+ grid-template-columns: repeat(1, 1fr);
+ gap: 20px;
+ max-height: calc(100vh - 240px);
+ overflow-y: auto;
+ padding-right: 10px;
+ }
+
+ /* 鑷畾涔夋粴鍔ㄦ潯鏍峰紡 */
+ .route-card-list::-webkit-scrollbar {
+ width: 8px;
+ }
+
+ .route-card-list::-webkit-scrollbar-track {
+ background: #f1f1f1;
+ border-radius: 4px;
+ }
+
+ .route-card-list::-webkit-scrollbar-thumb {
+ background: #c1c1c1;
+ border-radius: 4px;
+ }
+
+ .route-card-list::-webkit-scrollbar-thumb:hover {
+ background: #a8a8a8;
+ }
+
+ .route-card {
+ background: #fff;
+ border-radius: 8px;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+ overflow: hidden;
+
+ .card-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 20px 40px;
+ border-bottom: 1px solid #ebeef5;
+ background: #f8f9fa;
+
+ .route-info {
+ display: flex;
+ // flex-direction: column;
+ // justify-content: center;
+ // items-align: center;
+ gap: 4px;
+
+ .route-code {
+ font-size: 12px;
+ color: #909399;
+ font-family: "Courier New", monospace;
+ line-height: 30px;
+ }
+
+ .route-name {
+ font-size: 18px;
+ font-weight: 600;
+ color: #303133;
+ display: flex;
+ align-items: center;
+ }
+ }
+
+ .route-actions {
+ display: flex;
+ gap: 8px;
+
+ // .el-button {
+ // color: #409eff;
+ // }
+ }
+ }
+
+ .card-body {
+ padding: 16px 40px;
+
+ .route-desc {
+ font-size: 14px;
+ color: #606266;
+ margin-bottom: 12px;
+ }
+
+ .route-meta {
+ display: flex;
+ gap: 24px;
+ margin-bottom: 12px;
+ padding: 10px 14px;
+ background: linear-gradient(135deg, #f5f7fa 0%, #e8ecf1 100%);
+ border-radius: 8px;
+ border-left: 3px solid #409eff;
+
+ .meta-item {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ font-size: 13px;
+ margin-right: 40px;
+
+ .el-icon {
+ font-size: 14px;
+ color: #409eff;
+ }
+
+ .meta-label {
+ color: #909399;
+ font-weight: 500;
+ }
+
+ .meta-value {
+ color: #303133;
+ font-weight: 600;
+ }
+ }
+ }
+
+ .expand-btn-wrapper {
+ display: flex;
+ justify-content: center;
+ margin-top: 8px;
+
+ .expand-btn {
+ padding: 8px 20px;
+ border-radius: 20px;
+ background: linear-gradient(135deg, #ecf5ff 0%, #d9ecff 100%);
+ border: 1px solid #b3d8ff;
+ transition: all 0.3s ease;
+
+ .btn-text {
+ font-size: 13px;
+ font-weight: 500;
+ color: #409eff;
+ margin-right: 6px;
+ }
+
+ .expand-icon {
+ font-size: 14px;
+ color: #409eff;
+ transition: transform 0.3s ease;
+ }
+
+ &:hover {
+ background: linear-gradient(135deg, #409eff 0%, #66b1ff 100%);
+ border-color: #409eff;
+ box-shadow: 0 4px 12px rgba(64, 158, 255, 0.3);
+
+ .btn-text,
+ .expand-icon {
+ color: #fff;
+ }
+ }
+
+ &.expanded {
+ background: linear-gradient(135deg, #f0f9eb 0%, #e1f3d8 100%);
+ border-color: #a5d69a;
+
+ .btn-text,
+ .expand-icon {
+ color: #67c23a;
+ }
+
+ &:hover {
+ background: linear-gradient(135deg, #67c23a 0%, #85ce61 100%);
+ border-color: #67c23a;
+ box-shadow: 0 4px 12px rgba(103, 194, 58, 0.3);
+
+ .btn-text,
+ .expand-icon {
+ color: #fff;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ .process-route {
+ padding: 0 20px 20px;
+ background: #f5f7fa;
+ border-top: 1px solid #ebeef5;
+
+ .process-flow {
+ display: flex;
+ align-items: flex-start;
+ gap: 8px;
+ padding: 20px 0;
+ overflow-x: auto;
+ overflow-y: hidden;
+
+ .process-flow-item {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+
+ .process-node {
+ background: #fff;
+ border-radius: 12px;
+ padding: 16px;
+ border: 2px solid #ebeef5;
+ cursor: move;
+ transition: all 0.3s ease;
+ // min-width: 180px;
+ // max-width: 220px;
+ width: 300px;
+
+ &.expanded {
+ width: 400px;
+ }
+
+ &:hover {
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+ transform: translateY(-2px);
+ border-color: #409eff;
+ }
+
+ &:active {
+ cursor: grabbing;
+ }
+
+ .process-node-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 12px;
+
+ .process-number {
+ width: 28px;
+ height: 28px;
+ border-radius: 50%;
+ background: #409eff;
+ color: #ffffff;
+ font-size: 12px;
+ font-weight: 600;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+
+ .process-actions {
+ display: flex;
+ gap: 4px;
+ }
+ }
+
+ .process-node-body {
+ text-align: center;
+ margin-bottom: 12px;
+
+ .process-code {
+ font-size: 11px;
+ color: #909399;
+ font-family: "Courier New", monospace;
+ margin-bottom: 4px;
+ }
+
+ .process-name {
+ font-size: 15px;
+ font-weight: 600;
+ color: #303133;
+ margin-bottom: 6px;
+ }
+
+ .process-desc {
+ font-size: 12px;
+ color: #606266;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ }
+ }
+
+ .process-node-footer {
+ display: flex;
+ justify-content: flex-end;
+ align-items: center;
+ padding-top: 10px;
+ border-top: 1px solid #ebeef5;
+ }
+
+ .process-params-section {
+ margin-top: 12px;
+ padding-top: 12px;
+ border-top: 1px solid #ebeef5;
+
+ .params-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 8px;
+ font-size: 13px;
+ font-weight: 600;
+ color: #303133;
+ }
+
+ .params-list {
+ display: flex;
+ flex-direction: column;
+ gap: 6px;
+ max-height: 200px;
+ overflow-y: auto;
+
+ .param-item {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 6px 8px;
+ background: #fafafa;
+ border-radius: 4px;
+ border-left: 2px solid #409eff;
+ font-size: 12px;
+
+ .param-info {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ gap: 6px;
+ flex: 1;
+ min-width: 0;
+
+ .param-code {
+ font-size: 11px;
+ color: #e6a23c;
+ font-family: "Courier New", monospace;
+ margin-right: 20px;
+ }
+
+ .param-name {
+ font-size: 12px;
+ color: #303133;
+ font-weight: 500;
+ margin-right: 20px;
+ }
+
+ .param-value {
+ font-size: 11px;
+ color: #606266;
+ }
+ }
+
+ .param-actions {
+ display: flex;
+ gap: 4px;
+ flex-shrink: 0;
+ }
+ }
+ }
+ }
+ }
+
+ .flow-arrow {
+ display: flex;
+ align-items: center;
+ color: #c0c4cc;
+ font-size: 24px;
+ padding: 0 4px;
+
+ .el-icon {
+ font-size: 20px;
+ }
+ }
+ }
+
+ .add-process-node {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ min-width: 100px;
+ height: 137px;
+ border: 2px dashed #dcdfe6;
+ border-radius: 12px;
+ background: #fafafa;
+ cursor: pointer;
+ transition: all 0.3s ease;
+ color: #909399;
+ // margin-left: 10px;
+
+ .el-icon {
+ font-size: 24px;
+ margin-bottom: 8px;
+ }
+
+ span {
+ font-size: 13px;
+ }
+
+ &:hover {
+ border-color: #409eff;
+ background: #ecf5ff;
+ color: #409eff;
+ }
+ }
+ }
+ }
+ }
+
+ // 鎷栨嫿鏃剁殑鏍峰紡
+ .process-flow-item.dragging {
+ opacity: 0.5;
+ transform: scale(0.98);
+ }
+
+ // 閫夋嫨宸ュ簭瀵硅瘽妗嗘牱寮�
+ .process-select-container {
+ display: flex;
+ gap: 20px;
+ height: 450px;
+
+ .process-list-area {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+
+ .area-title {
+ font-size: 14px;
+ font-weight: 600;
+ color: #303133;
+ margin-bottom: 12px;
+ padding-bottom: 8px;
+ border-bottom: 1px solid #ebeef5;
+ }
+
+ .search-box {
+ margin-bottom: 12px;
+
+ .el-input {
+ width: 100%;
+ }
+ }
+ }
+
+ .process-detail-area {
+ width: 380px;
+ display: flex;
+ flex-direction: column;
+ background: #f5f7fa;
+ border-radius: 8px;
+ padding: 16px;
+
+ .area-title {
+ font-size: 14px;
+ font-weight: 600;
+ color: #303133;
+ margin-bottom: 16px;
+ padding-bottom: 8px;
+ border-bottom: 1px solid #ebeef5;
+ }
+
+ .process-detail-form {
+ .el-form-item {
+ margin-bottom: 12px;
+
+ .el-form-item__label {
+ color: #606266;
+ font-weight: 500;
+ }
+ }
+
+ .detail-text {
+ color: #303133;
+ font-weight: 500;
+ }
+ }
+ }
+ }
+
+ // 閫夋嫨鍙傛暟瀵硅瘽妗嗘牱寮�
+ .param-select-container {
+ display: flex;
+ gap: 20px;
+ height: 450px;
+
+ .param-list-area {
+ // flex: 1;
+ width: 380px;
+ display: flex;
+ flex-direction: column;
+
+ .area-title {
+ font-size: 14px;
+ font-weight: 600;
+ color: #303133;
+ margin-bottom: 12px;
+ padding-bottom: 8px;
+ border-bottom: 1px solid #ebeef5;
+ }
+
+ .search-box {
+ margin-bottom: 12px;
+
+ .el-input {
+ width: 100%;
+ }
+ }
+ }
+
+ .param-detail-area {
+ // width: 380px;
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ background: #f5f7fa;
+ border-radius: 8px;
+ padding: 16px;
+
+ .area-title {
+ font-size: 14px;
+ font-weight: 600;
+ color: #303133;
+ margin-bottom: 16px;
+ padding-bottom: 8px;
+ border-bottom: 1px solid #ebeef5;
+ }
+
+ .param-detail-form {
+ .el-form-item {
+ margin-bottom: 12px;
+
+ .el-form-item__label {
+ color: #606266;
+ font-weight: 500;
+ }
+ }
+
+ .detail-text {
+ color: #303133;
+ font-weight: 500;
+ }
+ }
+ }
+ }
+
+ // 鍒嗛〉鎺т欢鏍峰紡
+ .pagination-container {
+ position: fixed;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ display: flex;
+ justify-content: flex-end;
+ padding: 16px 20px;
+ background-color: #fff !important;
+ border-top: 1px solid #ebeef5;
+ box-shadow: 0 -2px 12px 0 rgba(0, 0, 0, 0.1);
+ z-index: 100;
+
+ .el-pagination {
+ .el-pagination__sizes {
+ margin-right: 16px;
+ }
+
+ .el-pagination__jump {
+ margin-left: 16px;
+ }
+
+ .el-pagination__total {
+ color: #606266;
+ font-size: 14px;
+ }
+
+ .el-pagination__button {
+ border-radius: 4px;
+ transition: all 0.3s ease;
+
+ &:hover:not(:disabled) {
+ color: #409eff;
+ border-color: #409eff;
+ }
+ }
+
+ .el-pagination__button--active {
+ background-color: #409eff;
+ border-color: #409eff;
+ color: #fff;
+ }
+ }
+ }
+</style>
--
Gitblit v1.9.3