| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <div class="search_form"> |
| | | <el-form :model="searchForm" |
| | | :inline="true"> |
| | | <el-form-item label="工序名称:"> |
| | | <el-input v-model="searchForm.name" |
| | | placeholder="请输入" |
| | | clearable |
| | | prefix-icon="Search" |
| | | style="width: 200px;" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="工序编号:"> |
| | | <el-input v-model="searchForm.no" |
| | | placeholder="请输入" |
| | | clearable |
| | | prefix-icon="Search" |
| | | style="width: 200px;" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <div class="process-config-container"> |
| | | <!-- 左侧工序列表 --> |
| | | <div class="process-list-section"> |
| | | <div class="section-header"> |
| | | <h3 class="section-title">工序列表</h3> |
| | | <el-button type="primary" |
| | | @click="handleQuery">搜索</el-button> |
| | | size="small" |
| | | @click="handleAddProcess"> |
| | | <el-icon> |
| | | <Plus /> |
| | | </el-icon>新增工序 |
| | | </el-button> |
| | | </div> |
| | | <div class="process-card-list"> |
| | | <div v-for="process in processList" |
| | | :key="process.id" |
| | | class="process-card" |
| | | :class="{ active: selectedProcess?.id === process.id }" |
| | | @click="selectProcess(process)"> |
| | | <div class="card-header"> |
| | | <span class="process-code">{{ process.processCode }}</span> |
| | | <div class="card-actions"> |
| | | <el-button link |
| | | type="primary" |
| | | @click.stop="handleEditProcess(process)"> |
| | | <el-icon> |
| | | <Edit /> |
| | | </el-icon> |
| | | 编辑 |
| | | </el-button> |
| | | <el-button link |
| | | type="danger" |
| | | @click.stop="handleDeleteProcess(process)"> |
| | | <el-icon> |
| | | <Delete /> |
| | | </el-icon> |
| | | 删除 |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | <div class="card-body"> |
| | | <div class="process-name">{{ process.processName }}</div> |
| | | <div class="process-desc">{{ process.processDesc || '暂无描述' }}</div> |
| | | </div> |
| | | <div class="card-footer"> |
| | | <el-tag size="small" |
| | | :type="process.status === '1' ? 'success' : 'info'"> |
| | | {{ process.status === '1' ? '启用' : '停用' }} |
| | | </el-tag> |
| | | <span class="param-count">参数: {{ process.paramCount || 0 }}个</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <!-- 右侧参数列表 --> |
| | | <div class="param-list-section"> |
| | | <div class="section-header"> |
| | | <h3 class="section-title"> |
| | | {{ selectedProcess ? selectedProcess.processName + ' - 参数配置' : '请选择工序' }} |
| | | </h3> |
| | | <el-button type="primary" |
| | | size="small" |
| | | :disabled="!selectedProcess" |
| | | @click="handleSelectParam"> |
| | | <el-icon> |
| | | <Plus /> |
| | | </el-icon>选择参数 |
| | | </el-button> |
| | | </div> |
| | | <div class="param-table-wrapper"> |
| | | <PIMTable v-if="selectedProcess" |
| | | rowKey="id" |
| | | :column="paramColumn" |
| | | :tableData="paramList" |
| | | :page="paramPage" |
| | | height="calc(100vh - 280px)" |
| | | :tableLoading="paramLoading" |
| | | :isSelection="false" |
| | | @pagination="handleParamPagination" /> |
| | | <div v-else |
| | | class="empty-tip"> |
| | | <el-empty description="请从左侧选择一个工序" /> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <!-- 工序新增/编辑对话框 --> |
| | | <el-dialog v-model="processDialogVisible" |
| | | :title="isProcessEdit ? '编辑工序' : '新增工序'" |
| | | width="500px"> |
| | | <el-form :model="processForm" |
| | | :rules="processRules" |
| | | ref="processFormRef" |
| | | label-width="100px"> |
| | | <el-form-item label="工序编码" |
| | | prop="processCode"> |
| | | <el-input v-model="processForm.processCode" |
| | | placeholder="请输入工序编码" /> |
| | | </el-form-item> |
| | | <el-form-item label="工序名称" |
| | | prop="processName"> |
| | | <el-input v-model="processForm.processName" |
| | | placeholder="请输入工序名称" /> |
| | | </el-form-item> |
| | | <el-form-item label="工序描述" |
| | | prop="processDesc"> |
| | | <el-input v-model="processForm.processDesc" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请输入工序描述" /> |
| | | </el-form-item> |
| | | <el-form-item label="状态" |
| | | prop="status"> |
| | | <el-radio-group v-model="processForm.status"> |
| | | <el-radio label="1">启用</el-radio> |
| | | <el-radio label="0">停用</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="info" |
| | | plain |
| | | @click="handleImport">导入</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="paramDialogVisible" |
| | | 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="360" |
| | | border |
| | | highlight-current-row |
| | | @current-change="handleParamSelect"> |
| | | <el-table-column prop="parameterCode" |
| | | label="参数编号" |
| | | width="100" /> |
| | | <el-table-column prop="parameterName" |
| | | label="参数名称" /> |
| | | <el-table-column prop="parameterType" |
| | | label="参数类型" |
| | | width="100"> |
| | | <template #default="scope"> |
| | | <el-tag size="small" |
| | | :type="getParamTypeTag(scope.row.parameterType)"> |
| | | {{ scope.row.parameterType }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </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.parameterCode }}</span> |
| | | </el-form-item> |
| | | <el-form-item label="参数名称"> |
| | | <span class="detail-text">{{ selectedParam.parameterName }}</span> |
| | | </el-form-item> |
| | | <el-form-item label="参数模式"> |
| | | <el-tag size="small" |
| | | :type="selectedParam.parameterType2 === '1' ? 'success' : 'warning'"> |
| | | {{ selectedParam.parameterType2 === '1' ? '单值' : '区间' }} |
| | | </el-tag> |
| | | </el-form-item> |
| | | <el-form-item label="参数类型"> |
| | | <el-tag size="small" |
| | | :type="getParamTypeTag(selectedParam.parameterType)"> |
| | | {{ selectedParam.parameterType }} |
| | | </el-tag> |
| | | </el-form-item> |
| | | <el-form-item label="参数格式"> |
| | | <span class="detail-text">{{ selectedParam.parameterFormat || '-' }}</span> |
| | | </el-form-item> |
| | | <el-form-item label="标准值"> |
| | | <span class="detail-text">{{ selectedParam.standardValue }}</span> |
| | | </el-form-item> |
| | | <el-form-item label="单位"> |
| | | <span class="detail-text">{{ selectedParam.unit || '-' }}</span> |
| | | </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"></PIMTable> |
| | | </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" /> |
| | | <ImportDialog ref="importDialogRef" |
| | | v-model="importDialogVisible" |
| | | title="导入工序" |
| | | :action="importAction" |
| | | :headers="importHeaders" |
| | | :auto-upload="false" |
| | | :on-success="handleImportSuccess" |
| | | :on-error="handleImportError" |
| | | @confirm="handleImportConfirm" |
| | | @download-template="handleDownloadTemplate" |
| | | @close="handleImportClose" /> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button @click="paramDialogVisible = false">取消</el-button> |
| | | <el-button type="primary" |
| | | :disabled="!selectedParam" |
| | | @click="handleParamSubmit">确定</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { onMounted, ref, reactive, toRefs, getCurrentInstance } from "vue"; |
| | | import NewProcess from "@/views/productionManagement/productionProcess/New.vue"; |
| | | import EditProcess from "@/views/productionManagement/productionProcess/Edit.vue"; |
| | | import ImportDialog from "@/components/Dialog/ImportDialog.vue"; |
| | | import { |
| | | listPage, |
| | | del, |
| | | importData, |
| | | downloadTemplate, |
| | | } from "@/api/productionManagement/productionProcess.js"; |
| | | import { getToken } from "@/utils/auth"; |
| | | import { ref, reactive, onMounted } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import { Plus, Edit, Delete, Search } from "@element-plus/icons-vue"; |
| | | import PIMTable from "@/components/PIMTable/PIMTable.vue"; |
| | | import { listType } from "@/api/system/dict/type"; |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | name: "", |
| | | no: "", |
| | | }, |
| | | // 工序列表数据 |
| | | const processList = ref([]); |
| | | const selectedProcess = ref(null); |
| | | const processLoading = ref(false); |
| | | |
| | | // 参数列表数据 |
| | | const paramList = ref([]); |
| | | const paramLoading = ref(false); |
| | | const paramPage = reactive({ |
| | | current: 1, |
| | | size: 10, |
| | | total: 0, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "工序编号", |
| | | prop: "no", |
| | | }, |
| | | { |
| | | label: "工序名称", |
| | | prop: "name", |
| | | }, |
| | | |
| | | // 数据字典 |
| | | const dictTypes = ref([]); |
| | | |
| | | // 工序对话框 |
| | | const processDialogVisible = ref(false); |
| | | const isProcessEdit = ref(false); |
| | | const processFormRef = ref(null); |
| | | const processForm = reactive({ |
| | | id: null, |
| | | processCode: "", |
| | | processName: "", |
| | | processDesc: "", |
| | | status: "1", |
| | | }); |
| | | const processRules = { |
| | | processCode: [{ required: true, message: "请输入工序编码", trigger: "blur" }], |
| | | processName: [{ required: true, message: "请输入工序名称", trigger: "blur" }], |
| | | }; |
| | | |
| | | // 参数对话框 |
| | | const paramDialogVisible = ref(false); |
| | | const availableParamList = ref([]); |
| | | const filteredParamList = ref([]); |
| | | const selectedParam = ref(null); |
| | | const paramSearchKeyword = ref(""); |
| | | |
| | | // 参数表格列配置 |
| | | const paramColumn = ref([ |
| | | { |
| | | label: "工资定额", |
| | | prop: "salaryQuota", |
| | | label: "参数编号", |
| | | prop: "parameterCode", |
| | | className: "code-cell", |
| | | }, |
| | | { |
| | | label: "备注", |
| | | prop: "remark", |
| | | label: "参数名称", |
| | | prop: "parameterName", |
| | | }, |
| | | { |
| | | label: "更新时间", |
| | | prop: "updateTime", |
| | | label: "参数模式", |
| | | prop: "parameterType2", |
| | | dataType: "tag", |
| | | formatType: row => (row.parameterType2 === "1" ? "success" : "warning"), |
| | | formatData: row => (row.parameterType2 === "1" ? "单值" : "区间"), |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "参数类型", |
| | | prop: "parameterType", |
| | | dataType: "tag", |
| | | formatType: row => { |
| | | const typeMap = { |
| | | 数值格式: "primary", |
| | | 文本格式: "info", |
| | | 下拉选项: "warning", |
| | | 时间格式: "success", |
| | | }; |
| | | return typeMap[row.parameterType] || "default"; |
| | | }, |
| | | }, |
| | | { |
| | | label: "参数格式", |
| | | prop: "parameterFormat", |
| | | }, |
| | | { |
| | | label: "标准值", |
| | | prop: "standardValue", |
| | | className: row => (row.parameterType === "数值格式" ? "quantity-cell" : ""), |
| | | }, |
| | | { |
| | | label: "单位", |
| | | prop: "unit", |
| | | }, |
| | | { |
| | | label: "操作", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 280, |
| | | dataType: "action", |
| | | width: "100", |
| | | operation: [ |
| | | { |
| | | name: "编辑", |
| | | type: "text", |
| | | clickFun: row => { |
| | | showEditModal(row); |
| | | }, |
| | | name: "删除", |
| | | clickFun: row => handleDeleteParam(row), |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const tableLoading = ref(false); |
| | | const isShowNewModal = ref(false); |
| | | const isShowEditModal = ref(false); |
| | | const record = ref({}); |
| | | const importDialogVisible = ref(false); |
| | | const importDialogRef = ref(null); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | const { proxy } = getCurrentInstance(); |
| | | |
| | | // 导入相关配置 |
| | | const importAction = |
| | | import.meta.env.VITE_APP_BASE_API + "/productProcess/importData"; |
| | | const importHeaders = { Authorization: "Bearer " + getToken() }; |
| | | |
| | | // 查询列表 |
| | | /** 搜索按钮操作 */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | // 获取工序列表 |
| | | const getProcessList = () => { |
| | | // 假数据 |
| | | processList.value = [ |
| | | { |
| | | id: 1, |
| | | processCode: "PROC001", |
| | | processName: "原料配比", |
| | | processDesc: "原材料配比工序", |
| | | status: "1", |
| | | paramCount: 3, |
| | | }, |
| | | { |
| | | id: 2, |
| | | processCode: "PROC002", |
| | | processName: "搅拌混合", |
| | | processDesc: "搅拌混合工序", |
| | | status: "1", |
| | | paramCount: 2, |
| | | }, |
| | | { |
| | | id: 3, |
| | | processCode: "PROC003", |
| | | processName: "浇筑成型", |
| | | processDesc: "浇筑成型工序", |
| | | status: "1", |
| | | paramCount: 4, |
| | | }, |
| | | { |
| | | id: 4, |
| | | processCode: "PROC004", |
| | | processName: "蒸压养护", |
| | | processDesc: "蒸压养护工序", |
| | | status: "0", |
| | | paramCount: 2, |
| | | }, |
| | | { |
| | | id: 5, |
| | | processCode: "PROC005", |
| | | processName: "切割加工", |
| | | processDesc: "切割加工工序", |
| | | status: "1", |
| | | paramCount: 3, |
| | | }, |
| | | ]; |
| | | }; |
| | | |
| | | 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 getParamList = processId => { |
| | | paramLoading.value = true; |
| | | // 假数据 |
| | | setTimeout(() => { |
| | | paramLoading.value = false; |
| | | const mockData = { |
| | | 1: [ |
| | | { |
| | | id: 1, |
| | | parameterCode: "P001", |
| | | parameterName: "水泥比例", |
| | | parameterType2: "1", |
| | | parameterType: "数值格式", |
| | | parameterFormat: "", |
| | | standardValue: "30", |
| | | unit: "%", |
| | | }, |
| | | { |
| | | id: 2, |
| | | parameterCode: "P002", |
| | | parameterName: "砂比例", |
| | | parameterType2: "1", |
| | | parameterType: "数值格式", |
| | | parameterFormat: "", |
| | | standardValue: "60", |
| | | unit: "%", |
| | | }, |
| | | { |
| | | id: 3, |
| | | parameterCode: "P003", |
| | | parameterName: "水比例", |
| | | parameterType2: "1", |
| | | parameterType: "数值格式", |
| | | parameterFormat: "", |
| | | standardValue: "10", |
| | | unit: "%", |
| | | }, |
| | | ], |
| | | 2: [ |
| | | { |
| | | id: 4, |
| | | parameterCode: "P004", |
| | | parameterName: "搅拌时间", |
| | | parameterType2: "1", |
| | | parameterType: "数值格式", |
| | | parameterFormat: "", |
| | | standardValue: "5", |
| | | unit: "分钟", |
| | | }, |
| | | { |
| | | id: 5, |
| | | parameterCode: "P005", |
| | | parameterName: "搅拌速度", |
| | | parameterType2: "2", |
| | | parameterType: "数值格式", |
| | | parameterFormat: "", |
| | | standardValue: "100-200", |
| | | unit: "rpm", |
| | | }, |
| | | ], |
| | | 3: [ |
| | | { |
| | | id: 6, |
| | | parameterCode: "P006", |
| | | parameterName: "浇筑温度", |
| | | parameterType2: "2", |
| | | parameterType: "数值格式", |
| | | parameterFormat: "", |
| | | standardValue: "20-30", |
| | | unit: "℃", |
| | | }, |
| | | { |
| | | id: 7, |
| | | parameterCode: "P007", |
| | | parameterName: "浇筑压力", |
| | | parameterType2: "1", |
| | | parameterType: "数值格式", |
| | | parameterFormat: "", |
| | | standardValue: "0.5", |
| | | unit: "MPa", |
| | | }, |
| | | { |
| | | id: 8, |
| | | parameterCode: "P008", |
| | | parameterName: "成型状态", |
| | | parameterType2: "1", |
| | | parameterType: "下拉选项", |
| | | parameterFormat: "status", |
| | | standardValue: "正常", |
| | | unit: "", |
| | | }, |
| | | { |
| | | id: 9, |
| | | parameterCode: "P009", |
| | | parameterName: "成型时间", |
| | | parameterType2: "1", |
| | | parameterType: "时间格式", |
| | | parameterFormat: "YYYY-MM-DD HH:mm:ss", |
| | | standardValue: "2024-01-01 08:00:00", |
| | | unit: "", |
| | | }, |
| | | ], |
| | | 4: [ |
| | | { |
| | | id: 10, |
| | | parameterCode: "P010", |
| | | parameterName: "蒸压温度", |
| | | parameterType2: "2", |
| | | parameterType: "数值格式", |
| | | parameterFormat: "", |
| | | standardValue: "180-200", |
| | | unit: "℃", |
| | | }, |
| | | { |
| | | id: 11, |
| | | parameterCode: "P011", |
| | | parameterName: "蒸压压力", |
| | | parameterType2: "1", |
| | | parameterType: "数值格式", |
| | | parameterFormat: "", |
| | | standardValue: "1.2", |
| | | unit: "MPa", |
| | | }, |
| | | ], |
| | | 5: [ |
| | | { |
| | | id: 12, |
| | | parameterCode: "P012", |
| | | parameterName: "切割尺寸", |
| | | parameterType2: "1", |
| | | parameterType: "文本格式", |
| | | parameterFormat: "", |
| | | standardValue: "600x200x100", |
| | | unit: "mm", |
| | | }, |
| | | { |
| | | id: 13, |
| | | parameterCode: "P013", |
| | | parameterName: "切割精度", |
| | | parameterType2: "1", |
| | | parameterType: "数值格式", |
| | | parameterFormat: "", |
| | | standardValue: "±1", |
| | | unit: "mm", |
| | | }, |
| | | { |
| | | id: 14, |
| | | parameterCode: "P014", |
| | | parameterName: "切割速度", |
| | | parameterType2: "1", |
| | | parameterType: "数值格式", |
| | | parameterFormat: "", |
| | | standardValue: "2", |
| | | unit: "m/min", |
| | | }, |
| | | ], |
| | | }; |
| | | paramList.value = mockData[processId] || []; |
| | | paramPage.total = paramList.value.length; |
| | | }, 300); |
| | | }; |
| | | |
| | | // 打开新增弹框 |
| | | const showNewModal = () => { |
| | | isShowNewModal.value = true; |
| | | // 选择工序 |
| | | const selectProcess = process => { |
| | | selectedProcess.value = process; |
| | | getParamList(process.id); |
| | | }; |
| | | |
| | | const showEditModal = row => { |
| | | isShowEditModal.value = true; |
| | | record.value = row; |
| | | // 工序操作 |
| | | const handleAddProcess = () => { |
| | | isProcessEdit.value = false; |
| | | processForm.id = null; |
| | | processForm.processCode = ""; |
| | | processForm.processName = ""; |
| | | processForm.processDesc = ""; |
| | | processForm.status = "1"; |
| | | processDialogVisible.value = true; |
| | | }; |
| | | |
| | | // 删除 |
| | | function handleDelete() { |
| | | const no = selectedRows.value.map(item => item.no); |
| | | const ids = selectedRows.value.map(item => item.id); |
| | | if (no.length > 2) { |
| | | proxy.$modal |
| | | .confirm( |
| | | '是否确认删除工序编号为"' + |
| | | no[0] + |
| | | "、" + |
| | | no[1] + |
| | | '"等' + |
| | | no.length + |
| | | "条数据项?" |
| | | ) |
| | | .then(function () { |
| | | return del(ids); |
| | | }) |
| | | .then(() => { |
| | | getList(); |
| | | proxy.$modal.msgSuccess("删除成功"); |
| | | }) |
| | | .catch(() => {}); |
| | | } else { |
| | | proxy.$modal |
| | | .confirm('是否确认删除工序编号为"' + no + '"的数据项?') |
| | | .then(function () { |
| | | return del(ids); |
| | | }) |
| | | .then(() => { |
| | | getList(); |
| | | proxy.$modal.msgSuccess("删除成功"); |
| | | }) |
| | | .catch(() => {}); |
| | | } |
| | | } |
| | | |
| | | // 导入 |
| | | const handleImport = () => { |
| | | importDialogVisible.value = true; |
| | | const handleEditProcess = process => { |
| | | isProcessEdit.value = true; |
| | | processForm.id = process.id; |
| | | processForm.processCode = process.processCode; |
| | | processForm.processName = process.processName; |
| | | processForm.processDesc = process.processDesc; |
| | | processForm.status = process.status; |
| | | processDialogVisible.value = true; |
| | | }; |
| | | |
| | | // 确认导入 |
| | | const handleImportConfirm = () => { |
| | | if (importDialogRef.value) { |
| | | importDialogRef.value.submit(); |
| | | } |
| | | }; |
| | | |
| | | // 导入成功 |
| | | const handleImportSuccess = response => { |
| | | if (response.code === 200) { |
| | | proxy.$modal.msgSuccess("导入成功"); |
| | | importDialogVisible.value = false; |
| | | if (importDialogRef.value) { |
| | | importDialogRef.value.clearFiles(); |
| | | const handleDeleteProcess = process => { |
| | | ElMessageBox.confirm("确定要删除该工序吗?", "提示", { |
| | | confirmButtonText: "确定", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }).then(() => { |
| | | ElMessage.success("删除成功"); |
| | | getProcessList(); |
| | | if (selectedProcess.value?.id === process.id) { |
| | | selectedProcess.value = null; |
| | | paramList.value = []; |
| | | } |
| | | getList(); |
| | | }); |
| | | }; |
| | | |
| | | const handleProcessSubmit = () => { |
| | | processFormRef.value.validate(valid => { |
| | | if (valid) { |
| | | ElMessage.success(isProcessEdit.value ? "编辑成功" : "新增成功"); |
| | | processDialogVisible.value = false; |
| | | getProcessList(); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // 参数操作 |
| | | const handleSelectParam = () => { |
| | | if (!selectedProcess.value) { |
| | | ElMessage.warning("请先选择一个工序"); |
| | | return; |
| | | } |
| | | // 获取可选参数列表(假数据) |
| | | availableParamList.value = [ |
| | | { |
| | | id: 101, |
| | | parameterCode: "P101", |
| | | parameterName: "温度", |
| | | parameterType2: "2", |
| | | parameterType: "数值格式", |
| | | parameterFormat: "", |
| | | standardValue: "20-30", |
| | | unit: "℃", |
| | | }, |
| | | { |
| | | id: 102, |
| | | parameterCode: "P102", |
| | | parameterName: "压力", |
| | | parameterType2: "1", |
| | | parameterType: "数值格式", |
| | | parameterFormat: "", |
| | | standardValue: "0.5", |
| | | unit: "MPa", |
| | | }, |
| | | { |
| | | id: 103, |
| | | parameterCode: "P103", |
| | | parameterName: "湿度", |
| | | parameterType2: "2", |
| | | parameterType: "数值格式", |
| | | parameterFormat: "", |
| | | standardValue: "40-60", |
| | | unit: "%", |
| | | }, |
| | | { |
| | | id: 104, |
| | | parameterCode: "P104", |
| | | parameterName: "速度", |
| | | parameterType2: "1", |
| | | parameterType: "数值格式", |
| | | parameterFormat: "", |
| | | standardValue: "100", |
| | | unit: "m/min", |
| | | }, |
| | | { |
| | | id: 105, |
| | | parameterCode: "P105", |
| | | parameterName: "状态", |
| | | parameterType2: "1", |
| | | parameterType: "下拉选项", |
| | | parameterFormat: "status", |
| | | standardValue: "正常", |
| | | unit: "", |
| | | }, |
| | | { |
| | | id: 106, |
| | | parameterCode: "P106", |
| | | parameterName: "记录时间", |
| | | parameterType2: "1", |
| | | parameterType: "时间格式", |
| | | parameterFormat: "YYYY-MM-DD HH:mm:ss", |
| | | standardValue: "2024-01-01 08:00:00", |
| | | unit: "", |
| | | }, |
| | | { |
| | | id: 107, |
| | | parameterCode: "P107", |
| | | parameterName: "备注", |
| | | parameterType2: "1", |
| | | parameterType: "文本格式", |
| | | parameterFormat: "", |
| | | standardValue: "无", |
| | | unit: "", |
| | | }, |
| | | ]; |
| | | filteredParamList.value = availableParamList.value; |
| | | paramSearchKeyword.value = ""; |
| | | selectedParam.value = null; |
| | | paramDialogVisible.value = true; |
| | | }; |
| | | |
| | | const handleParamSelect = row => { |
| | | selectedParam.value = row; |
| | | }; |
| | | |
| | | const handleParamSearch = () => { |
| | | const keyword = paramSearchKeyword.value.trim().toLowerCase(); |
| | | if (!keyword) { |
| | | filteredParamList.value = availableParamList.value; |
| | | } else { |
| | | proxy.$modal.msgError(response.msg || "导入失败"); |
| | | filteredParamList.value = availableParamList.value.filter(item => |
| | | item.parameterName.toLowerCase().includes(keyword) |
| | | ); |
| | | } |
| | | }; |
| | | |
| | | // 导入失败 |
| | | const handleImportError = error => { |
| | | proxy.$modal.msgError("导入失败:" + (error.message || "未知错误")); |
| | | const getParamTypeTag = type => { |
| | | const typeMap = { |
| | | 数值格式: "primary", |
| | | 文本格式: "info", |
| | | 下拉选项: "warning", |
| | | 时间格式: "success", |
| | | }; |
| | | return typeMap[type] || "default"; |
| | | }; |
| | | |
| | | // 关闭导入弹窗 |
| | | const handleImportClose = () => { |
| | | if (importDialogRef.value) { |
| | | importDialogRef.value.clearFiles(); |
| | | const handleDeleteParam = row => { |
| | | ElMessageBox.confirm("确定要删除该参数吗?", "提示", { |
| | | confirmButtonText: "确定", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }).then(() => { |
| | | ElMessage.success("删除成功"); |
| | | getParamList(selectedProcess.value.id); |
| | | }); |
| | | }; |
| | | |
| | | const handleParamSubmit = () => { |
| | | if (!selectedParam.value) { |
| | | ElMessage.warning("请先选择一个参数"); |
| | | return; |
| | | } |
| | | ElMessage.success("添加成功"); |
| | | paramDialogVisible.value = false; |
| | | getParamList(selectedProcess.value.id); |
| | | }; |
| | | |
| | | // 下载模板 |
| | | const handleDownloadTemplate = async () => { |
| | | try { |
| | | const res = await downloadTemplate(); |
| | | const blob = new Blob([res], { |
| | | type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", |
| | | }); |
| | | const url = window.URL.createObjectURL(blob); |
| | | const link = document.createElement("a"); |
| | | link.href = url; |
| | | link.download = "工序导入模板.xlsx"; |
| | | link.click(); |
| | | window.URL.revokeObjectURL(url); |
| | | proxy.$modal.msgSuccess("模板下载成功"); |
| | | } catch (error) { |
| | | proxy.$modal.msgError("模板下载失败"); |
| | | } |
| | | const handleParamPagination = obj => { |
| | | paramPage.current = obj.page; |
| | | paramPage.size = obj.limit; |
| | | getParamList(selectedProcess.value.id); |
| | | }; |
| | | |
| | | // 导出 |
| | | // const handleOut = () => { |
| | | // ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", { |
| | | // confirmButtonText: "确认", |
| | | // cancelButtonText: "取消", |
| | | // type: "warning", |
| | | // }) |
| | | // .then(() => { |
| | | // proxy.download("/salesLedger/scheduling/exportTwo", {}, "工序排产.xlsx"); |
| | | // }) |
| | | // .catch(() => { |
| | | // proxy.$modal.msg("已取消"); |
| | | // }); |
| | | // }; |
| | | // 获取数据字典 |
| | | const getDictTypes = () => { |
| | | listType({ pageNum: 1, pageSize: 1000 }).then(res => { |
| | | dictTypes.value = res.rows || []; |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | getProcessList(); |
| | | getDictTypes(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped></style> |
| | | <style scoped lang="scss"> |
| | | .app-container { |
| | | padding: 20px; |
| | | background-color: #f0f2f5; |
| | | min-height: calc(100vh - 84px); |
| | | } |
| | | |
| | | .process-config-container { |
| | | display: flex; |
| | | gap: 20px; |
| | | height: calc(100vh - 124px); |
| | | } |
| | | |
| | | // 左侧工序列表 |
| | | .process-list-section { |
| | | width: 370px; |
| | | background: #fff; |
| | | border-radius: 8px; |
| | | box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .section-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 16px 20px; |
| | | border-bottom: 1px solid #ebeef5; |
| | | |
| | | .section-title { |
| | | margin: 0; |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | } |
| | | } |
| | | |
| | | .process-card-list { |
| | | flex: 1; |
| | | overflow-y: auto; |
| | | padding: 16px; |
| | | } |
| | | |
| | | .process-card { |
| | | background: #fff; |
| | | border: 1px solid #ebeef5; |
| | | border-radius: 8px; |
| | | padding: 16px; |
| | | margin-bottom: 12px; |
| | | cursor: pointer; |
| | | transition: all 0.3s ease; |
| | | |
| | | &:hover { |
| | | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); |
| | | transform: translateY(-2px); |
| | | } |
| | | |
| | | &.active { |
| | | border-color: #409eff; |
| | | background: #f5f7fa; |
| | | box-shadow: 0 4px 12px rgba(64, 158, 255, 0.2); |
| | | } |
| | | |
| | | .card-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 8px; |
| | | |
| | | .process-code { |
| | | font-size: 12px; |
| | | color: #909399; |
| | | font-family: "Courier New", monospace; |
| | | } |
| | | |
| | | .card-actions { |
| | | display: flex; |
| | | gap: 4px; |
| | | |
| | | .el-button { |
| | | padding: 4px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .card-body { |
| | | margin-bottom: 12px; |
| | | |
| | | .process-name { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | margin-bottom: 4px; |
| | | } |
| | | |
| | | .process-desc { |
| | | font-size: 12px; |
| | | color: #909399; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | } |
| | | } |
| | | |
| | | .card-footer { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | |
| | | .param-count { |
| | | font-size: 12px; |
| | | color: #606266; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 右侧参数列表 |
| | | .param-list-section { |
| | | flex: 1; |
| | | background: #fff; |
| | | border-radius: 8px; |
| | | box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .param-table-wrapper { |
| | | flex: 1; |
| | | padding: 0 20px 20px; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .empty-tip { |
| | | flex: 1; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | // 表格样式 |
| | | :deep(.el-table) { |
| | | border: none; |
| | | border-radius: 6px; |
| | | overflow: hidden; |
| | | |
| | | .el-table__header-wrapper { |
| | | background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
| | | |
| | | th { |
| | | background: transparent; |
| | | font-weight: 600; |
| | | color: #ffffff; |
| | | border-bottom: none; |
| | | padding: 16px 0; |
| | | } |
| | | } |
| | | |
| | | .el-table__body-wrapper { |
| | | tr { |
| | | transition: all 0.3s ease; |
| | | |
| | | &:hover { |
| | | background: linear-gradient( |
| | | 90deg, |
| | | rgba(102, 126, 234, 0.05) 0%, |
| | | rgba(118, 75, 162, 0.05) 100% |
| | | ); |
| | | } |
| | | |
| | | td { |
| | | border-bottom: 1px solid #f0f0f0; |
| | | padding: 14px 0; |
| | | color: #303133; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 编码单元格样式 |
| | | :deep(.code-cell) { |
| | | color: #e6a23c; |
| | | font-family: "Courier New", monospace; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | // 数值单元格样式 |
| | | :deep(.quantity-cell) { |
| | | font-weight: 600; |
| | | color: #409eff; |
| | | font-family: "Courier New", monospace; |
| | | } |
| | | |
| | | // 选择参数对话框样式 |
| | | .param-select-container { |
| | | display: flex; |
| | | gap: 20px; |
| | | height: 450px; |
| | | |
| | | .param-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%; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .param-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; |
| | | } |
| | | |
| | | .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; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |