| | |
| | | method: "delete", |
| | | }); |
| | | } |
| | | // 获取工序参数列表 |
| | | export function getProcessParamList(query) { |
| | | return request({ |
| | | url: `/ProcessRouteItemParam/pageList`, |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | // 工艺路线参数新增 |
| | | export function addProcessRouteItemParam(data) { |
| | | return request({ |
| | | url: "/ProcessRouteItemParam/save", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | // 工艺路线参数修改 |
| | | export function editProcessRouteItemParam(data) { |
| | | return request({ |
| | | url: "/ProcessRouteItemParam/edit", |
| | | method: "put", |
| | | data: data, |
| | | }); |
| | | } |
| | | // 工艺路线参数修改 |
| | | export function delProcessRouteItemParam(id) { |
| | | return request({ |
| | | url: `/ProcessRouteItemParam/remove/${id}`, |
| | | method: "delete", |
| | | }); |
| | | } |
| | |
| | | :align="item.align" |
| | | :sortable="!!item.sortable" |
| | | :type="item.type" |
| | | :width="item.width"> |
| | | :width="item.width" |
| | | :class-name="item.className || ''"> |
| | | <template #header="scope"> |
| | | <div class="pim-table-header-cell"> |
| | | <div class="pim-table-header-title"> |
| | |
| | | <!-- 可点击的文字 --> |
| | | <div v-else-if="item.dataType == 'link'" |
| | | class="cell link" |
| | | :class="item.className || ''" |
| | | style="width: 100%" |
| | | @click="goLink(scope.row, item.linkMethod)"> |
| | | <span v-if="!item.formatData">{{ scope.row[item.prop] }}</span> |
| | |
| | | <!-- 默认纯展示数据 --> |
| | | <div v-else |
| | | class="cell" |
| | | :class="item.className || ''" |
| | | style="width: 100%"> |
| | | <span v-if="!item.formatData">{{ scope.row[item.prop] }}</span> |
| | | <span v-else>{{ |
| | |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | height="calc(100vh - 280px)" |
| | | height="calc(100vh - 320px)" |
| | | :tableLoading="tableLoading" |
| | | :isSelection="false" |
| | | :isShowPagination="false" |
| | | :isShowPagination="true" |
| | | @pagination="pagination"> |
| | | </PIMTable> |
| | | </div> |
| | |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | // 调用新接口 /baseParam/list |
| | | getBaseParamList({ paramName: searchForm.paramName }) |
| | | getBaseParamList({ |
| | | paramName: searchForm.paramName, |
| | | current: page.current, |
| | | size: page.size, |
| | | }) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | if (res.code === 200) { |
| | | tableData.value = res.data || []; |
| | | page.total = res.data?.length || 0; |
| | | tableData.value = res.data?.records || []; |
| | | page.total = res.data?.total || 0; |
| | | } else { |
| | | ElMessage.error(res.msg || "查询失败"); |
| | | } |
| | |
| | | <div class="route-info"> |
| | | <span class="route-name"><el-icon style="margin-right: 8px;line-height: 30px;"> |
| | | <ScaleToOriginal /> |
| | | </el-icon>{{ route.routeName }}<el-tag style="margin-left: 8px" |
| | | :type="route.status == 1 ? 'warning' : 'success'">{{ route.status == 1 ? '草稿' : '批准' }}</el-tag></span> |
| | | <span class="route-code">{{ route.routeCode }}</span> |
| | | </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 === '1'" |
| | | <el-button v-if="!route.status" |
| | | link |
| | | type="success" |
| | | @click="handleApproveRoute(route)"> |
| | |
| | | </el-icon> |
| | | 批准 |
| | | </el-button> |
| | | <el-button v-if="route.status === '2'" |
| | | <el-button v-if="route.status" |
| | | link |
| | | type="warning" |
| | | @click="handleRevokeApproveRoute(route)"> |
| | |
| | | <Document /> |
| | | </el-icon> |
| | | <span class="meta-label">BOM:</span> |
| | | <span class="meta-value">{{ route.bomId || '-' }}</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.routeDesc || '暂无描述' }}</span> |
| | | <span class="meta-label">备注:</span> |
| | | <span class="meta-value">{{ route.description || '暂无描述' }}</span> |
| | | </span> |
| | | </div> |
| | | <div class="expand-btn-wrapper"> |
| | |
| | | <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> |
| | |
| | | </div> |
| | | </div> |
| | | <div class="process-node-body"> |
| | | <div class="process-code">{{ process.processCode }}</div> |
| | | <!-- <div class="process-code">{{ process.processId }}</div> --> |
| | | <div class="process-name">{{ process.processName }}</div> |
| | | <div class="process-desc">{{ process.processDesc || '暂无描述' }}</div> |
| | | <!-- <div class="process-desc">{{ process.remark || '暂无描述' }}</div> --> |
| | | </div> |
| | | <div class="process-node-footer"> |
| | | <!-- <el-tag size="small" |
| | |
| | | size="small" |
| | | @click="toggleProcessParams(process)"> |
| | | {{ process.expanded ? '收起参数' : '展开参数' }} |
| | | ({{ process.paramList?.length || 0 }}) |
| | | ({{ process.paramCount }}) |
| | | </el-button> |
| | | </div> |
| | | <div v-if="process.expanded" |
| | |
| | | :key="param.id" |
| | | class="param-item"> |
| | | <div class="param-info"> |
| | | <span class="param-code">{{ param.parameterCode }}</span> |
| | | <span class="param-name">{{ param.parameterName }}</span> |
| | | <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 class="param-value">标准值:{{ param.standardValue }} {{ param.unit }}</span> |
| | | <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 |
| | |
| | | <span>新增工序</span> |
| | | </div> |
| | | </div> |
| | | <el-empty v-if="!route.processList || route.processList.length === 0" |
| | | description="暂无工序" |
| | | :image-size="80" /> |
| | | </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" |
| | |
| | | <el-form-item label="产品名称" |
| | | prop="productModelId"> |
| | | <el-button type="primary" |
| | | @click="showProductSelectDialog = true"> |
| | | @click="handleProcessProductSelectClick2"> |
| | | {{ routeForm.productName && routeForm.productModelName |
| | | ? `${routeForm.productName} - ${routeForm.productModelName}` |
| | | : '选择产品' }} |
| | |
| | | <el-form-item label="路线编码" |
| | | prop="routeCode"> |
| | | <el-input v-model="routeForm.routeCode" |
| | | placeholder="请输入路线编码" /> |
| | | disabled |
| | | placeholder="自动生成" /> |
| | | </el-form-item> |
| | | <el-form-item label="路线名称" |
| | | prop="routeName"> |
| | | <el-input v-model="routeForm.routeName" |
| | | placeholder="请输入路线名称" /> |
| | | </el-form-item> |
| | | <el-form-item label="路线描述" |
| | | prop="routeDesc"> |
| | | <el-input v-model="routeForm.routeDesc" |
| | | <el-form-item label="备注" |
| | | prop="description"> |
| | | <el-input v-model="routeForm.description" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请输入路线描述" /> |
| | |
| | | ref="processFormRef" |
| | | label-width="120px"> |
| | | <el-form-item label="工序编码" |
| | | prop="processCode"> |
| | | <el-input v-model="processForm.processCode" |
| | | prop="no"> |
| | | <el-input v-model="processForm.no" |
| | | placeholder="请输入工序编码" /> |
| | | </el-form-item> |
| | | <el-form-item label="工序名称" |
| | | prop="processName"> |
| | | <el-input v-model="processForm.processName" |
| | | prop="name"> |
| | | <el-input v-model="processForm.name" |
| | | placeholder="请输入工序名称" /> |
| | | </el-form-item> |
| | | <el-form-item label="工序描述" |
| | | prop="processDesc"> |
| | | <el-input v-model="processForm.processDesc" |
| | | prop="remark"> |
| | | <el-input v-model="processForm.remark" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请输入工序描述" /> |
| | |
| | | <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 :label="true">启用</el-radio> |
| | | <el-radio :label="false">停用</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | </el-form> |
| | |
| | | border |
| | | highlight-current-row |
| | | @current-change="handleProcessSelect"> |
| | | <el-table-column prop="processCode" |
| | | <el-table-column prop="no" |
| | | label="工序编号" |
| | | width="100" /> |
| | | <el-table-column prop="processName" |
| | | <el-table-column prop="name" |
| | | label="工序名称" /> |
| | | <el-table-column prop="processDesc" |
| | | <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 === '1' ? 'success' : 'info'"> |
| | | {{ scope.row.status === '1' ? '启用' : '停用' }} |
| | | :type="scope.row.status ? 'success' : 'info'"> |
| | | {{ scope.row.status ? '启用' : '停用' }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | <div class="process-detail-area"> |
| | | <div class="area-title">工序详情</div> |
| | | <el-form v-if="selectedProcessItem" |
| | | :model="selectedProcessItem" |
| | | :model="processForm" |
| | | label-width="100px" |
| | | class="process-detail-form"> |
| | | <el-form-item label="工序编号"> |
| | | <span class="detail-text">{{ selectedProcessItem.processCode }}</span> |
| | | <span class="detail-text">{{ selectedProcessItem.no }}</span> |
| | | </el-form-item> |
| | | <el-form-item label="工序名称"> |
| | | <span class="detail-text">{{ selectedProcessItem.processName }}</span> |
| | | <span class="detail-text">{{ selectedProcessItem.name }}</span> |
| | | </el-form-item> |
| | | <el-form-item label="工序描述"> |
| | | <span class="detail-text">{{ selectedProcessItem.processDesc || '-' }}</span> |
| | | <span class="detail-text">{{ selectedProcessItem.remark || '-' }}</span> |
| | | </el-form-item> |
| | | <el-form-item label="状态"> |
| | | <el-tag size="small" |
| | | :type="selectedProcessItem.status === '1' ? 'success' : 'info'"> |
| | | {{ selectedProcessItem.status === '1' ? '启用' : '停用' }} |
| | | :type="selectedProcessItem.status ? 'success' : 'info'"> |
| | | {{ selectedProcessItem.status ? '启用' : '停用' }} |
| | | </el-tag> |
| | | </el-form-item> |
| | | <el-form-item label="参数数量"> |
| | | <span class="detail-text">{{ selectedProcessItem.paramCount || 0 }}个</span> |
| | | <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 |
| | |
| | | <span class="dialog-footer"> |
| | | <el-button @click="selectProcessDialogVisible = false">取消</el-button> |
| | | <el-button type="primary" |
| | | :disabled="!selectedProcessItem" |
| | | :disabled="!selectedProcessItem || !processForm.productModelId" |
| | | @click="handleProcessSelectSubmit">确定</el-button> |
| | | </span> |
| | | </template> |
| | |
| | | </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 { ref, reactive, getCurrentInstance } from "vue"; |
| | | import { ref, reactive, getCurrentInstance, onMounted } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import { |
| | | Plus, |
| | |
| | | } 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 routeList = ref([]); |
| | | const dictTypes = ref([]); |
| | | |
| | | // 工艺路线分页 |
| | | const routePage = reactive({ |
| | | current: 1, |
| | | size: 10, |
| | | total: 0, |
| | | }); |
| | | |
| | | // 获取全局实例 |
| | | const { proxy } = getCurrentInstance(); |
| | |
| | | productModelName: "", |
| | | bomId: null, |
| | | routeCode: "", |
| | | routeName: "", |
| | | routeDesc: "", |
| | | status: "1", |
| | | description: "", |
| | | status: true, |
| | | }); |
| | | const routeRules = { |
| | | productModelId: [ |
| | | { required: true, message: "请选择产品", trigger: "change" }, |
| | | ], |
| | | bomId: [{ required: true, message: "请选择BOM", trigger: "change" }], |
| | | routeCode: [{ required: true, message: "请输入路线编码", trigger: "blur" }], |
| | | routeName: [{ required: true, message: "请输入路线名称", trigger: "blur" }], |
| | | }; |
| | | |
| | | // 工序对话框 |
| | |
| | | const currentRouteId = ref(null); |
| | | const processForm = reactive({ |
| | | id: null, |
| | | processCode: "", |
| | | processName: "", |
| | | processDesc: "", |
| | | status: "1", |
| | | no: "", |
| | | name: "", |
| | | remark: "", |
| | | status: true, |
| | | }); |
| | | const processRules = { |
| | | processCode: [{ required: true, message: "请输入工序编码", trigger: "blur" }], |
| | | processName: [{ required: true, message: "请输入工序名称", trigger: "blur" }], |
| | | no: [{ required: true, message: "请输入工序编码", trigger: "blur" }], |
| | | name: [{ required: true, message: "请输入工序名称", trigger: "blur" }], |
| | | }; |
| | | |
| | | // 选择工序对话框 |
| | |
| | | ], |
| | | }; |
| | | |
| | | // 选择参数对话框 |
| | | 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: [ |
| | | { |
| | | required: true, |
| | | message: "请输入标准值", |
| | | trigger: "blur", |
| | | validator: (rule, value, callback) => { |
| | | if (value === null || value === undefined || value === "") { |
| | | callback(new Error("请输入标准值")); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }, |
| | | }, |
| | | ], |
| | | minValue: [ |
| | | { |
| | | 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 = () => { |
| | | routeList.value = [ |
| | | { |
| | | id: 1, |
| | | productModelId: 1, |
| | | productName: "标准砌块", |
| | | productModelName: "3.5型", |
| | | bomId: 1, |
| | | routeCode: "ROUTE001", |
| | | routeName: "标准砌块生产线", |
| | | routeDesc: "标准砌块生产流程", |
| | | status: "1", |
| | | expanded: false, |
| | | processList: [ |
| | | { |
| | | id: 1, |
| | | processCode: "PROC001", |
| | | processName: "原料配比", |
| | | processDesc: "原材料配比工序", |
| | | status: "1", |
| | | // 导入 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, |
| | | paramList: [ |
| | | { |
| | | 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: 2, |
| | | processCode: "PROC002", |
| | | processName: "搅拌混合", |
| | | processDesc: "搅拌混合工序", |
| | | status: "1", |
| | | expanded: false, |
| | | paramList: [ |
| | | { |
| | | id: 3, |
| | | parameterCode: "P003", |
| | | parameterName: "搅拌时间", |
| | | parameterType2: "1", |
| | | parameterType: "数值格式", |
| | | parameterFormat: "", |
| | | standardValue: "5", |
| | | unit: "分钟", |
| | | }, |
| | | ], |
| | | }, |
| | | { |
| | | id: 3, |
| | | processCode: "PROC003", |
| | | processName: "浇筑成型", |
| | | processDesc: "浇筑成型工序", |
| | | status: "1", |
| | | expanded: false, |
| | | paramList: [], |
| | | }, |
| | | ], |
| | | }, |
| | | { |
| | | id: 2, |
| | | productModelId: 2, |
| | | productName: "板材", |
| | | productModelName: "5.0型", |
| | | bomId: 2, |
| | | routeCode: "ROUTE002", |
| | | routeName: "板材生产线", |
| | | routeDesc: "板材生产流程", |
| | | status: "1", |
| | | expanded: false, |
| | | processList: [ |
| | | { |
| | | id: 4, |
| | | processCode: "PROC004", |
| | | processName: "切割加工", |
| | | processDesc: "切割加工工序", |
| | | status: "1", |
| | | expanded: false, |
| | | paramList: [ |
| | | { |
| | | id: 4, |
| | | parameterCode: "P004", |
| | | parameterName: "切割尺寸", |
| | | parameterType2: "1", |
| | | parameterType: "文本格式", |
| | | parameterFormat: "", |
| | | standardValue: "600x200x100", |
| | | unit: "mm", |
| | | }, |
| | | ], |
| | | }, |
| | | ], |
| | | }, |
| | | ]; |
| | | 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.productModelName = ""; |
| | | routeForm.bomId = null; |
| | | routeForm.routeCode = ""; |
| | | routeForm.routeName = ""; |
| | | routeForm.routeDesc = ""; |
| | | routeForm.status = "1"; |
| | | routeForm.description = ""; |
| | | routeForm.status = false; |
| | | bomOptions.value = []; |
| | | routeDialogVisible.value = true; |
| | | }; |
| | |
| | | routeForm.productModelName = route.productModelName; |
| | | routeForm.bomId = route.bomId; |
| | | routeForm.routeCode = route.routeCode; |
| | | routeForm.routeName = route.routeName; |
| | | routeForm.routeDesc = route.routeDesc; |
| | | routeForm.description = route.description; |
| | | routeForm.status = route.status; |
| | | routeDialogVisible.value = true; |
| | | }; |
| | |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }).then(() => { |
| | | ElMessage.success("删除成功"); |
| | | getRouteList(); |
| | | del(route.id) |
| | | .then(res => { |
| | | ElMessage.success("删除成功"); |
| | | getRouteList(); |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error("删除失败"); |
| | | }); |
| | | }); |
| | | }; |
| | | |
| | | const handleRouteSubmit = () => { |
| | | routeFormRef.value.validate(valid => { |
| | | if (valid) { |
| | | ElMessage.success(isRouteEdit.value ? "编辑成功" : "新增成功"); |
| | | routeDialogVisible.value = false; |
| | | getRouteList(); |
| | | // 构建提交数据 |
| | | const submitData = { |
| | | ...routeForm, |
| | | // 注意:API 期望的字段名可能与表单字段名不同 |
| | | 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 isform2 = ref(null); |
| | | const handleProcessProductSelectClick = () => { |
| | | isform2.value = true; |
| | | showProductSelectDialog.value = true; |
| | | }; |
| | | const handleProcessProductSelectClick2 = () => { |
| | | isform2.value = false; |
| | | showProductSelectDialog.value = true; |
| | | }; |
| | | |
| | | // 产品选择处理 |
| | | const handleProductSelect = async products => { |
| | | if (products && products.length > 0) { |
| | | const product = products[0]; |
| | | // 先查询BOM列表(必选) |
| | | try { |
| | | const res = await getByModel(product.id); |
| | | // 处理返回的BOM数据:可能是数组、对象或包含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]; |
| | | } |
| | | if (isform2.value) { |
| | | // 帮我写工序中的选择产品的回调,并且把字段加进processForm |
| | | if (products && products.length > 0) { |
| | | const product = products[0]; |
| | | console.log("product:", product); |
| | | // 把product中的字段添加到processForm中 |
| | | // Object.assign(processForm, product); |
| | | processForm.productModelId = product.id; |
| | | processForm.productName = product.productName; |
| | | processForm.model = product.model; |
| | | processForm.unit = product.unit || ""; |
| | | console.log("processForm:", processForm); |
| | | |
| | | 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.$refs["processFormRef"]?.validateField("productModelId"); |
| | | } |
| | | } else { |
| | | if (products && products.length > 0) { |
| | | const product = products[0]; |
| | | // 先查询BOM列表(必选) |
| | | try { |
| | | const res = await getByModel(product.id); |
| | | // 处理返回的BOM数据:可能是数组、对象或包含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("该产品没有BOM,请先创建BOM"); |
| | | } |
| | | } catch (error) { |
| | | // 如果接口返回404或其他错误,说明没有BOM |
| | | proxy.$modal.msgError("该产品没有BOM,请先创建BOM"); |
| | | } |
| | | } catch (error) { |
| | | // 如果接口返回404或其他错误,说明没有BOM |
| | | proxy.$modal.msgError("该产品没有BOM,请先创建BOM"); |
| | | } |
| | | } |
| | | }; |
| | |
| | | cancelButtonText: "取消", |
| | | type: "info", |
| | | }).then(() => { |
| | | route.status = "2"; |
| | | ElMessage.success("批准成功"); |
| | | // 调用修改接口,只修改status字段为批准状态 |
| | | update({ id: route.id, status: true }) |
| | | .then(res => { |
| | | ElMessage.success("批准成功"); |
| | | getRouteList(); |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error("批准失败"); |
| | | }); |
| | | }); |
| | | }; |
| | | |
| | |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }).then(() => { |
| | | route.status = "1"; |
| | | ElMessage.success("撤销批准成功"); |
| | | // 调用修改接口,只修改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; |
| | | // 获取可选工序列表(假数据) |
| | | availableProcessList.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, |
| | | }, |
| | | ]; |
| | | // 重置搜索和选择状态 |
| | | 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; |
| | | }; |
| | | |
| | |
| | | currentRouteId.value = routeId; |
| | | isProcessEdit.value = true; |
| | | processForm.id = process.id; |
| | | processForm.processCode = process.processCode; |
| | | processForm.processName = process.processName; |
| | | processForm.processDesc = process.processDesc; |
| | | processForm.no = process.no; |
| | | processForm.name = process.name; |
| | | processForm.remark = process.remark; |
| | | processForm.status = process.status; |
| | | processDialogVisible.value = true; |
| | | }; |
| | |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }).then(() => { |
| | | ElMessage.success("删除成功"); |
| | | getRouteList(); |
| | | // 调用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); |
| | | }); |
| | | }); |
| | | }; |
| | | |
| | |
| | | if (valid) { |
| | | ElMessage.success(isProcessEdit.value ? "编辑成功" : "新增成功"); |
| | | processDialogVisible.value = false; |
| | | getRouteList(); |
| | | // 调用接口更新工序列表 |
| | | 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); |
| | | }); |
| | | } |
| | | } |
| | | }); |
| | | }; |
| | |
| | | if (!keyword) { |
| | | filteredProcessList.value = availableProcessList.value; |
| | | } else { |
| | | filteredProcessList.value = availableProcessList.value.filter(item => |
| | | item.processName.toLowerCase().includes(keyword) |
| | | 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 = () => { |
| | |
| | | return; |
| | | } |
| | | |
| | | // 检查工序是否已存在 |
| | | const route = routeList.value[currentRouteIndex.value]; |
| | | const exists = route.processList.some( |
| | | p => p.id === selectedProcessItem.value.id |
| | | ); |
| | | if (exists) { |
| | | ElMessage.warning("该工序已存在于工艺路线中"); |
| | | if (!processForm.productModelId) { |
| | | ElMessage.warning("请选择产品"); |
| | | return; |
| | | } |
| | | |
| | | // 添加工序到工艺路线 |
| | | const newProcess = { |
| | | id: Date.now(), |
| | | processCode: selectedProcessItem.value.processCode, |
| | | processName: selectedProcessItem.value.processName, |
| | | processDesc: selectedProcessItem.value.processDesc, |
| | | status: selectedProcessItem.value.status, |
| | | paramList: [], |
| | | expanded: false, |
| | | // 构建请求参数 |
| | | const params = { |
| | | routeId: currentRouteId.value, |
| | | processId: selectedProcessItem.value.id, |
| | | dragSort: routePage.total + 1, |
| | | ...processForm, |
| | | }; |
| | | |
| | | route.processList.push(newProcess); |
| | | ElMessage.success("添加工序成功"); |
| | | selectProcessDialogVisible.value = false; |
| | | // 如果是修改操作,添加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; |
| | | isParamEdit.value = false; |
| | | paramForm.id = null; |
| | | paramForm.parameterCode = ""; |
| | | paramForm.parameterName = ""; |
| | | paramForm.parameterType2 = "1"; |
| | | paramForm.parameterType = ""; |
| | | paramForm.parameterFormat = ""; |
| | | paramForm.standardValue = ""; |
| | | paramForm.unit = ""; |
| | | paramDialogVisible.value = true; |
| | | 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; |
| | | isParamEdit.value = true; |
| | | paramForm.id = param.id; |
| | | paramForm.parameterCode = param.parameterCode; |
| | | paramForm.parameterName = param.parameterName; |
| | | paramForm.parameterType2 = param.parameterType2 || "1"; |
| | | paramForm.parameterType = param.parameterType; |
| | | paramForm.parameterFormat = param.parameterFormat; |
| | | paramForm.standardValue = param.standardValue; |
| | | paramForm.unit = param.unit; |
| | | paramDialogVisible.value = true; |
| | | 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) => { |
| | |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }).then(() => { |
| | | ElMessage.success("删除成功"); |
| | | getRouteList(); |
| | | // 调用API删除参数 |
| | | delProcessRouteItemParam(param.id) |
| | | .then(res => { |
| | | ElMessage.success("删除成功"); |
| | | // 刷新参数列表 |
| | | toggleProcessParams2(process); |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error("删除参数失败"); |
| | | console.error("删除参数失败:", err); |
| | | }); |
| | | }); |
| | | }; |
| | | |
| | |
| | | |
| | | const getParamTypeTag = type => { |
| | | const typeMap = { |
| | | 数值格式: "primary", |
| | | 文本格式: "info", |
| | | 下拉选项: "warning", |
| | | 时间格式: "success", |
| | | 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 route = routeList.value.find(r => r.id === routeId); |
| | | if (route && route.processList) { |
| | | const draggedProcess = route.processList[draggedItem.value]; |
| | | route.processList.splice(draggedItem.value, 1); |
| | | route.processList.splice(dropIndex, 0, draggedProcess); |
| | | ElMessage.success("排序成功"); |
| | | |
| | | // 计算新的排序值 |
| | | 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); |
| | | }); |
| | | } |
| | | }; |
| | | |
| | |
| | | |
| | | 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 lang="scss"> |
| | | .app-container { |
| | | padding: 20px; |
| | | padding-bottom: 80px; |
| | | background-color: #f0f2f5; |
| | | min-height: calc(100vh - 84px); |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .route-header { |
| | |
| | | } |
| | | |
| | | .route-card-list { |
| | | display: flex; |
| | | flex-direction: column; |
| | | 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 { |
| | |
| | | align-items: center; |
| | | justify-content: center; |
| | | min-width: 100px; |
| | | height: 175px; |
| | | height: 137px; |
| | | border: 2px dashed #dcdfe6; |
| | | border-radius: 12px; |
| | | background: #fafafa; |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 选择参数对话框样式 |
| | | .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> |
| | |
| | | </el-table-column> |
| | | <el-table-column label="BOM编号" |
| | | prop="bomNo" /> |
| | | <el-table-column label="产品编码" |
| | | prop="productCode" /> |
| | | <el-table-column label="产品名称" |
| | | prop="productName" /> |
| | | <el-table-column label="规格型号" |
| | |
| | | |
| | | // 从路由参数获取产品信息 |
| | | const routeBomNo = computed(() => route.query.bomNo || ""); |
| | | const routeProductCode = computed(() => route.query.productCode || ""); |
| | | const routeProductName = computed(() => route.query.productName || ""); |
| | | const routeProductModelName = computed( |
| | | () => route.query.productModelName || "" |
| | |
| | | prop="productModelId"> |
| | | <el-button type="primary" |
| | | @click="showProductSelectDialog = true"> |
| | | {{ form.productName || '选择产品' }} |
| | | {{ form.productName || '选择产品' }}-{{ form.productModelName }} |
| | | </el-button> |
| | | </el-form-item> |
| | | <el-form-item label="版本号" |
| | |
| | | minWidth: 140, |
| | | }, |
| | | { |
| | | label: "产品编码", |
| | | prop: "productCode", |
| | | |
| | | minWidth: 160, |
| | | }, |
| | | { |
| | | label: "产品名称", |
| | | prop: "productName", |
| | | |
| | |
| | | <el-button type="primary" |
| | | size="small" |
| | | :disabled="!selectedProcess" |
| | | @click="handleSelectParam"> |
| | | @click="openParamDialog"> |
| | | <el-icon> |
| | | <Plus /> |
| | | </el-icon>选择参数 |
| | |
| | | </el-input> |
| | | </div> |
| | | <el-table :data="filteredParamList" |
| | | height="360" |
| | | height="300" |
| | | border |
| | | highlight-current-row |
| | | @current-change="handleParamSelect"> |
| | |
| | | </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"> |
| | |
| | | // 参数列表数据 |
| | | const paramList = ref([]); |
| | | const paramLoading = ref(false); |
| | | const paramPage = reactive({ |
| | | current: 1, |
| | | size: 10, |
| | | total: 0, |
| | | }); |
| | | |
| | | // 数据字典 |
| | | const dictTypes = ref([]); |
| | |
| | | name: [{ required: true, message: "请输入工序名称", trigger: "blur" }], |
| | | salaryQuota: [ |
| | | { |
| | | required: true, |
| | | required: false, |
| | | message: "请输入工资定额", |
| | | trigger: "blur", |
| | | validator: (rule, value, callback) => { |
| | | if (value === null || value === undefined || value === "") { |
| | | callback(new Error("请输入工资定额")); |
| | | } else if (isNaN(value) || value < 0) { |
| | | if (isNaN(value) || value < 0) { |
| | | callback(new Error("工资定额必须是非负数字")); |
| | | } else { |
| | | callback(); |
| | |
| | | const filteredParamList = ref([]); |
| | | const selectedParam = ref(null); |
| | | const paramSearchKeyword = ref(""); |
| | | |
| | | // 可选参数分页 |
| | | const paramPage = reactive({ |
| | | current: 1, |
| | | size: 10, |
| | | total: 0, |
| | | }); |
| | | |
| | | // 编辑参数对话框 |
| | | const editParamDialogVisible = ref(false); |
| | |
| | | } |
| | | }); |
| | | }; |
| | | const openParamDialog = () => { |
| | | paramSearchKeyword.value = ""; |
| | | if (!selectedProcess.value) { |
| | | ElMessage.warning("请先选择一个工序"); |
| | | return; |
| | | } |
| | | // 获取可选参数列表 |
| | | 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 || "查询失败"); |
| | | } |
| | | }); |
| | | console.log(filteredParamList.value, "可选参数列表"); |
| | | selectedParam.value = null; |
| | | paramDialogVisible.value = true; |
| | | }; |
| | | |
| | | // 参数操作 |
| | | const handleSelectParam = () => { |
| | |
| | | return; |
| | | } |
| | | // 获取可选参数列表 |
| | | getBaseParamList({ paramName: paramSearchKeyword.value }).then(res => { |
| | | getBaseParamList({ |
| | | paramName: paramSearchKeyword.value, |
| | | current: paramPage.current, |
| | | size: paramPage.size, |
| | | }).then(res => { |
| | | if (res.code === 200) { |
| | | filteredParamList.value = res.data || []; |
| | | page.total = res.data?.length || 0; |
| | | filteredParamList.value = res.data?.records || []; |
| | | paramPage.total = res.data?.total || 0; |
| | | } else { |
| | | ElMessage.error(res.msg || "查询失败"); |
| | | } |
| | |
| | | }; |
| | | |
| | | const handleParamSearch = () => { |
| | | const keyword = paramSearchKeyword.value.trim().toLowerCase(); |
| | | if (!keyword) { |
| | | filteredParamList.value = availableParamList.value; |
| | | } else { |
| | | filteredParamList.value = availableParamList.value.filter(item => |
| | | item.paramName.toLowerCase().includes(keyword) |
| | | ); |
| | | } |
| | | // 重置分页 |
| | | paramPage.current = 1; |
| | | // 重新加载数据 |
| | | handleSelectParam(); |
| | | }; |
| | | |
| | | // 处理分页大小变化 |
| | | const handleParamSizeChange = size => { |
| | | paramPage.size = size; |
| | | handleSelectParam(); |
| | | }; |
| | | |
| | | // 处理当前页码变化 |
| | | const handleParamCurrentChange = current => { |
| | | paramPage.current = current; |
| | | handleSelectParam(); |
| | | }; |
| | | const getParamTypeText = type => { |
| | | const typeMap = { |
| | |
| | | th { |
| | | background: transparent; |
| | | font-weight: 600; |
| | | color: #ffffff; |
| | | // color: #ffffff; |
| | | border-bottom: none; |
| | | padding: 16px 0; |
| | | } |
| | |
| | | <el-col :xs="24" |
| | | :sm="24" |
| | | :md="12" |
| | | :lg="14" |
| | | :xl="14" |
| | | :lg="12" |
| | | :xl="12" |
| | | class="left-col"> |
| | | <div class="panel left-panel"> |
| | | <PIMTable rowKey="id" |
| | |
| | | <el-col :xs="24" |
| | | :sm="24" |
| | | :md="12" |
| | | :lg="10" |
| | | :xl="10" |
| | | :lg="12" |
| | | :xl="12" |
| | | class="right-col"> |
| | | <div class="panel right-panel"> |
| | | <div class="right-header"> |
| | |
| | | <el-table-column prop="productName" |
| | | label="产品名称" |
| | | min-width="140" /> |
| | | <el-table-column prop="materialCode" |
| | | label="物料编码" |
| | | min-width="140" /> |
| | | <el-table-column prop="model" |
| | | label="规格型号" |
| | | min-width="140" /> |
| | | <el-table-column label="操作" |
| | | width="120" |
| | | fixed="right" |
| | |
| | | <template> |
| | | <div> |
| | | <el-dialog |
| | | v-model="dialogFormVisible" |
| | | :title="operationType === 'add' ? '新增原材料检验' : '编辑原材料检验'" |
| | | width="70%" |
| | | @close="closeDia" |
| | | > |
| | | <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef"> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="供应商:" prop="supplier"> |
| | | <el-select |
| | | v-model="form.supplier" |
| | | placeholder="请选择" |
| | | clearable |
| | | :disabled="supplierQuantityDisabled" |
| | | > |
| | | <el-option |
| | | v-for="item in supplierList" |
| | | :key="item.id" |
| | | :label="item.supplierName" |
| | | :value="item.supplierName" |
| | | /> |
| | | <el-dialog v-model="dialogFormVisible" |
| | | :title="operationType === 'add' ? '新增原材料检验' : '编辑原材料检验'" |
| | | width="70%" |
| | | @close="closeDia"> |
| | | <el-form :model="form" |
| | | label-width="100px" |
| | | label-position="left" |
| | | :rules="rules" |
| | | ref="formRef" |
| | | class="inspection-form"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="8"> |
| | | <el-form-item label="供应商:" |
| | | prop="supplier"> |
| | | <el-input v-model="form.supplier" |
| | | placeholder="请输入" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="产品:" |
| | | prop="productId"> |
| | | <el-button type="primary" |
| | | @click="openProductSelectDialog" |
| | | :disabled="operationType === 'edit'" |
| | | class="product-select-btn">{{form.productName || "选择产品"}}{{form.model?(" - "+form.model):""}}</el-button> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="试样编号:" |
| | | prop="sampleCode"> |
| | | <el-input v-model="form.sampleCode" |
| | | placeholder="请输入" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="车牌号:" |
| | | prop="licensePlateNumber"> |
| | | <el-input v-model="form.licensePlateNumber" |
| | | placeholder="请输入" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="检测性质:" |
| | | prop="inspectNature"> |
| | | <el-select v-model="form.inspectNature" |
| | | style="width: 100%"> |
| | | <el-option label="日常检测" |
| | | value="日常检测" /> |
| | | <el-option label="入场验收" |
| | | value="入场验收" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="产品名称:" prop="productId"> |
| | | <el-tree-select |
| | | v-model="form.productId" |
| | | placeholder="请选择" |
| | | clearable |
| | | check-strictly |
| | | @change="getModels" |
| | | :data="productOptions" |
| | | :render-after-expand="false" |
| | | :disabled="operationType === 'edit'" |
| | | style="width: 100%" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="规格型号:" prop="productModelId"> |
| | | <el-select v-model="form.productModelId" placeholder="请选择" clearable :disabled="operationType === 'edit'" |
| | | filterable readonly @change="handleChangeModel"> |
| | | <el-option v-for="item in modelOptions" :key="item.id" :label="item.model" :value="item.id" /> |
| | | <el-col :span="8"> |
| | | <el-form-item label="试样状态:" |
| | | prop="sampleState"> |
| | | <el-select v-model="form.sampleState" |
| | | style="width: 100%"> |
| | | <el-option label="固体" |
| | | value="固体" /> |
| | | <el-option label="颗粒" |
| | | value="颗粒" /> |
| | | <el-option label="膏体" |
| | | value="膏体" /> |
| | | <el-option label="粉末" |
| | | value="粉末" /> |
| | | <el-option label="液体" |
| | | value="液体" /> |
| | | <el-option label="气体" |
| | | value="气体" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="指标选择:" prop="testStandardId"> |
| | | <el-select |
| | | v-model="form.testStandardId" |
| | | placeholder="请选择指标" |
| | | clearable |
| | | @change="handleTestStandardChange" |
| | | style="width: 100%" |
| | | > |
| | | <el-option |
| | | v-for="item in testStandardOptions" |
| | | :key="item.id" |
| | | :label="item.standardName || item.standardNo" |
| | | :value="item.id" |
| | | /> |
| | | <el-col :span="8"> |
| | | <el-form-item label="单位:" |
| | | prop="unit"> |
| | | <el-input v-model="form.unit" |
| | | disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="指标选择:" |
| | | prop="testStandardId"> |
| | | <el-select v-model="form.testStandardId" |
| | | placeholder="请选择指标" |
| | | clearable |
| | | @change="handleTestStandardChange" |
| | | style="width: 100%"> |
| | | <el-option v-for="item in testStandardOptions" |
| | | :key="item.id" |
| | | :label="item.standardName || item.standardNo" |
| | | :value="item.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="单位:" prop="unit"> |
| | | <el-input v-model="form.unit" disabled/> |
| | | <el-col :span="8"> |
| | | <el-form-item label="检测单位:" |
| | | prop="checkCompany"> |
| | | <el-input v-model="form.checkCompany" |
| | | placeholder="请输入" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="数量:" prop="quantity"> |
| | | <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="form.quantity" placeholder="请输入" |
| | | clearable :precision="2" :disabled="supplierQuantityDisabled"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="检测单位:" prop="checkCompany"> |
| | | <el-input v-model="form.checkCompany" placeholder="请输入" clearable/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="检测结果:" prop="checkResult"> |
| | | <el-select v-model="form.checkResult"> |
| | | <el-option label="合格" value="合格"/> |
| | | <el-option label="不合格" value="不合格"/> |
| | | <el-col :span="8"> |
| | | <el-form-item label="检测结果:" |
| | | prop="checkResult"> |
| | | <el-select v-model="form.checkResult" |
| | | style="width: 100%"> |
| | | <el-option label="合格" |
| | | value="合格" /> |
| | | <el-option label="不合格" |
| | | value="不合格" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="检验员:" prop="checkName"> |
| | | <el-select v-model="form.checkName" placeholder="请选择" clearable style="width: 100%"> |
| | | <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName" :value="item.nickName"/> |
| | | <el-col :span="8"> |
| | | <el-form-item label="检验员:" |
| | | prop="checkName"> |
| | | <el-select v-model="form.checkName" |
| | | placeholder="请选择" |
| | | clearable |
| | | style="width: 100%"> |
| | | <el-option v-for="item in userList" |
| | | :key="item.nickName" |
| | | :label="item.nickName" |
| | | :value="item.nickName" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="检测日期:" prop="checkTime"> |
| | | <el-date-picker |
| | | v-model="form.checkTime" |
| | | type="date" |
| | | placeholder="请选择日期" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | style="width: 100%" |
| | | /> |
| | | <el-col :span="8"> |
| | | <el-form-item label="检测日期:" |
| | | prop="checkTime"> |
| | | <el-date-picker v-model="form.checkTime" |
| | | type="date" |
| | | placeholder="请选择日期" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="取样日期:" |
| | | prop="sampleTime"> |
| | | <el-date-picker v-model="form.sampleTime" |
| | | type="date" |
| | | placeholder="请选择日期" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <!-- <div style="margin-bottom: 10px;text-align: right">--> |
| | | <!-- <el-button type="danger" plain @click="handleDelete">删除</el-button>--> |
| | | <!-- </div>--> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :tableLoading="tableLoading" |
| | | height="400" |
| | | > |
| | | <!-- <div style="margin-bottom: 10px;text-align: right">--> |
| | | <!-- <el-button type="danger" plain @click="handleDelete">删除</el-button>--> |
| | | <!-- </div>--> |
| | | <PIMTable rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :tableLoading="tableLoading" |
| | | height="400"> |
| | | <template #slot="{ row }"> |
| | | <el-input v-model="row.testValue" clearable/> |
| | | <el-input v-model="row.testValue" |
| | | clearable /> |
| | | </template> |
| | | </PIMTable> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm">确认</el-button> |
| | | <el-button type="primary" |
| | | @click="submitForm">确认</el-button> |
| | | <el-button @click="closeDia">取消</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | <!-- 产品选择对话框 --> |
| | | <ProductSelectDialog v-model="productSelectDialogVisible" |
| | | :single="true" |
| | | @confirm="handleProductSelect" /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref, reactive, toRefs, computed, getCurrentInstance, nextTick} from "vue"; |
| | | import {getOptions} from "@/api/procurementManagement/procurementLedger.js"; |
| | | import {modelList, productTreeList} from "@/api/basicData/product.js"; |
| | | import {qualityInspectAdd, qualityInspectUpdate} from "@/api/qualityManagement/rawMaterialInspection.js"; |
| | | import {qualityInspectParamDel, qualityInspectParamInfo} from "@/api/qualityManagement/qualityInspectParam.js"; |
| | | import {qualityInspectDetailByProductId, getQualityTestStandardParamByTestStandardId} from "@/api/qualityManagement/metricMaintenance.js"; |
| | | import {userListNoPage} from "@/api/system/user.js"; |
| | | import { |
| | | ref, |
| | | reactive, |
| | | toRefs, |
| | | computed, |
| | | getCurrentInstance, |
| | | nextTick, |
| | | } from "vue"; |
| | | import { getOptions } from "@/api/procurementManagement/procurementLedger.js"; |
| | | import { modelList, productTreeList } from "@/api/basicData/product.js"; |
| | | import { |
| | | qualityInspectAdd, |
| | | qualityInspectUpdate, |
| | | } from "@/api/qualityManagement/rawMaterialInspection.js"; |
| | | import { |
| | | qualityInspectParamDel, |
| | | qualityInspectParamInfo, |
| | | } from "@/api/qualityManagement/qualityInspectParam.js"; |
| | | import { |
| | | qualityInspectDetailByProductId, |
| | | getQualityTestStandardParamByTestStandardId, |
| | | } from "@/api/qualityManagement/metricMaintenance.js"; |
| | | import { userListNoPage } from "@/api/system/user.js"; |
| | | import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue"; |
| | | |
| | | const {proxy} = getCurrentInstance() |
| | | const emit = defineEmits(['close']) |
| | | const { proxy } = getCurrentInstance(); |
| | | const emit = defineEmits(["close"]); |
| | | |
| | | const dialogFormVisible = ref(false); |
| | | const operationType = ref('') |
| | | const data = reactive({ |
| | | form: { |
| | | checkTime: "", |
| | | supplier: "", |
| | | checkName: "", |
| | | productName: "", |
| | | productId: "", |
| | | productModelId: "", |
| | | model: "", |
| | | testStandardId: "", |
| | | unit: "", |
| | | quantity: "", |
| | | checkCompany: "", |
| | | checkResult: "", |
| | | }, |
| | | rules: { |
| | | checkTime: [{required: true, message: "请输入", trigger: "blur"},], |
| | | supplier: [{required: true, message: "请输入", trigger: "blur"}], |
| | | checkName: [{required: false, message: "请输入", trigger: "blur"}], |
| | | productId: [{required: true, message: "请输入", trigger: "blur"}], |
| | | productModelId: [{required: true, message: "请选择产品型号", trigger: "change"}], |
| | | testStandardId: [{required: false, message: "请选择指标", trigger: "change"}], |
| | | unit: [{required: false, message: "请输入", trigger: "blur"}], |
| | | quantity: [{required: true, message: "请输入", trigger: "blur"}], |
| | | checkCompany: [{required: false, message: "请输入", trigger: "blur"}], |
| | | checkResult: [{required: true, message: "请选择检测结果", trigger: "change"}], |
| | | }, |
| | | }); |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "指标", |
| | | prop: "parameterItem", |
| | | }, |
| | | { |
| | | label: "单位", |
| | | prop: "unit", |
| | | }, |
| | | { |
| | | label: "标准值", |
| | | prop: "standardValue", |
| | | }, |
| | | { |
| | | label: "内控值", |
| | | prop: "controlValue", |
| | | }, |
| | | { |
| | | label: "检验值", |
| | | prop: "testValue", |
| | | dataType: 'slot', |
| | | slot: 'slot', |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | const dialogFormVisible = ref(false); |
| | | const operationType = ref(""); |
| | | const data = reactive({ |
| | | form: { |
| | | checkTime: "", |
| | | supplier: "", |
| | | checkName: "", |
| | | productName: "", |
| | | productId: "", |
| | | productModelId: "", |
| | | model: "", |
| | | testStandardId: "", |
| | | unit: "", |
| | | quantity: "", |
| | | checkCompany: "", |
| | | checkResult: "", |
| | | inspectNature: "", |
| | | sampleCode: "", |
| | | sampleState: "", |
| | | licensePlateNumber: "", |
| | | sampleTime: "", |
| | | }, |
| | | rules: { |
| | | checkTime: [{ required: false, message: "请输入", trigger: "blur" }], |
| | | supplier: [{ required: true, message: "请输入", trigger: "blur" }], |
| | | checkName: [{ required: false, message: "请输入", trigger: "blur" }], |
| | | productId: [{ required: true, message: "请输入", trigger: "blur" }], |
| | | productModelId: [ |
| | | { required: true, message: "请选择产品型号", trigger: "change" }, |
| | | ], |
| | | testStandardId: [ |
| | | { required: false, message: "请选择指标", trigger: "change" }, |
| | | ], |
| | | unit: [{ required: false, message: "请输入", trigger: "blur" }], |
| | | quantity: [{ required: true, message: "请输入", trigger: "blur" }], |
| | | checkCompany: [{ required: false, message: "请输入", trigger: "blur" }], |
| | | checkResult: [ |
| | | { required: false, message: "请选择检测结果", trigger: "change" }, |
| | | ], |
| | | inspectNature: [ |
| | | { required: false, message: "请选择检测性质", trigger: "change" }, |
| | | ], |
| | | sampleState: [ |
| | | { required: false, message: "请选择试样状态", trigger: "change" }, |
| | | ], |
| | | sampleCode: [{ required: false, message: "请输入", trigger: "blur" }], |
| | | licensePlateNumber: [ |
| | | { required: false, message: "请输入", trigger: "blur" }, |
| | | ], |
| | | sampleTime: [{ required: false, message: "请输入", trigger: "blur" }], |
| | | }, |
| | | }); |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "指标", |
| | | prop: "parameterItem", |
| | | }, |
| | | { |
| | | label: "单位", |
| | | prop: "unit", |
| | | }, |
| | | { |
| | | label: "标准值", |
| | | prop: "standardValue", |
| | | }, |
| | | { |
| | | label: "内控值", |
| | | prop: "controlValue", |
| | | }, |
| | | { |
| | | label: "检验值", |
| | | prop: "testValue", |
| | | dataType: "slot", |
| | | slot: "slot", |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | |
| | | const {form, rules} = toRefs(data); |
| | | const supplierList = ref([]); |
| | | const productOptions = ref([]); |
| | | const currentProductId = ref(0); |
| | | const testStandardOptions = ref([]); // 指标选择下拉框数据 |
| | | const modelOptions = ref([]); |
| | | const userList = ref([]); // 检验员下拉列表 |
| | | const { form, rules } = toRefs(data); |
| | | const supplierList = ref([]); |
| | | const productOptions = ref([]); |
| | | const currentProductId = ref(0); |
| | | const testStandardOptions = ref([]); // 指标选择下拉框数据 |
| | | const modelOptions = ref([]); |
| | | const userList = ref([]); // 检验员下拉列表 |
| | | const productSelectDialogVisible = ref(false); |
| | | |
| | | // 编辑时:productMainId 或 purchaseLedgerId 任一有值则供应商、数量置灰 |
| | | const supplierQuantityDisabled = computed(() => { |
| | | const v = form.value || {}; |
| | | return !!(v.productMainId != null || v.purchaseLedgerId != null); |
| | | }); |
| | | |
| | | // 打开弹框 |
| | | const openDialog = async (type, row) => { |
| | | operationType.value = type; |
| | | getOptions().then((res) => { |
| | | supplierList.value = res.data; |
| | | // 编辑时:productMainId 或 purchaseLedgerId 任一有值则供应商、数量置灰 |
| | | const supplierQuantityDisabled = computed(() => { |
| | | const v = form.value || {}; |
| | | return !!(v.productMainId != null || v.purchaseLedgerId != null); |
| | | }); |
| | | |
| | | try { |
| | | const userRes = await userListNoPage(); |
| | | userList.value = userRes.data || []; |
| | | } catch (e) { |
| | | console.error("加载检验员列表失败", e); |
| | | userList.value = []; |
| | | } |
| | | // 先重置表单数据(保持字段完整,避免弹窗首次渲染时触发必填红框“闪一下”) |
| | | form.value = { |
| | | checkTime: "", |
| | | supplier: "", |
| | | checkName: "", |
| | | productName: "", |
| | | productId: "", |
| | | productModelId: "", |
| | | model: "", |
| | | testStandardId: "", |
| | | unit: "", |
| | | quantity: "", |
| | | checkCompany: "", |
| | | checkResult: "", |
| | | } |
| | | testStandardOptions.value = []; |
| | | tableData.value = []; |
| | | // 先确保产品树已加载,否则编辑时产品/规格型号无法反显 |
| | | await getProductOptions(); |
| | | if (operationType.value === 'edit') { |
| | | // 先保存 testStandardId,避免被清空 |
| | | const savedTestStandardId = row.testStandardId; |
| | | form.value = {...row} |
| | | currentProductId.value = row.productId || 0 |
| | | // 关键:编辑时加载规格型号下拉选项,才能反显 productModelId |
| | | if (currentProductId.value) { |
| | | try { |
| | | const res = await modelList({ id: currentProductId.value }); |
| | | modelOptions.value = res || []; |
| | | // 同步回填 model / unit(有些接口返回的 row 里可能没带全) |
| | | if (form.value.productModelId) { |
| | | handleChangeModel(form.value.productModelId); |
| | | } |
| | | } catch (e) { |
| | | console.error("加载规格型号失败", e); |
| | | modelOptions.value = []; |
| | | } |
| | | } |
| | | // 编辑模式下,先加载指标选项,然后加载参数列表 |
| | | if (currentProductId.value) { |
| | | // 先加载指标选项 |
| | | let params = { |
| | | productId: currentProductId.value, |
| | | inspectType: 0 |
| | | } |
| | | qualityInspectDetailByProductId(params).then(res => { |
| | | testStandardOptions.value = res.data || []; |
| | | // 使用 nextTick 和 setTimeout 确保选项已经渲染到 DOM |
| | | nextTick(() => { |
| | | setTimeout(() => { |
| | | // 如果编辑数据中有 testStandardId,则设置并加载对应的参数 |
| | | if (savedTestStandardId) { |
| | | // 确保类型匹配(item.id 可能是数字或字符串) |
| | | const matchedOption = testStandardOptions.value.find(item => |
| | | item.id == savedTestStandardId || String(item.id) === String(savedTestStandardId) |
| | | ); |
| | | if (matchedOption) { |
| | | // 确保使用匹配项的 id(保持类型一致) |
| | | form.value.testStandardId = matchedOption.id; |
| | | // 编辑保留原检验值,直接拉取原参数数据 |
| | | getQualityInspectParamList(row.id); |
| | | } else { |
| | | // 如果找不到匹配项,尝试直接使用原值 |
| | | console.warn('未找到匹配的指标选项,testStandardId:', savedTestStandardId, '可用选项:', testStandardOptions.value); |
| | | form.value.testStandardId = savedTestStandardId; |
| | | getQualityInspectParamList(row.id); |
| | | } |
| | | } else { |
| | | // 否则使用旧的逻辑 |
| | | getQualityInspectParamList(row.id); |
| | | } |
| | | }, 100); |
| | | }); |
| | | }); |
| | | } else { |
| | | getQualityInspectParamList(row.id); |
| | | } |
| | | } |
| | | // 最后再打开弹窗,并清理校验态,避免必填提示闪烁 |
| | | dialogFormVisible.value = true; |
| | | nextTick(() => { |
| | | proxy.$refs?.formRef?.clearValidate?.(); |
| | | }); |
| | | } |
| | | const getProductOptions = () => { |
| | | return productTreeList().then((res) => { |
| | | productOptions.value = convertIdToValue(res); |
| | | return productOptions.value; |
| | | }); |
| | | }; |
| | | const getModels = (value) => { |
| | | form.value.productModelId = undefined; |
| | | form.value.unit = undefined; |
| | | modelOptions.value = []; |
| | | currentProductId.value = value |
| | | form.value.productName = findNodeById(productOptions.value, value); |
| | | modelList({ id: value }).then((res) => { |
| | | modelOptions.value = res; |
| | | }) |
| | | if (currentProductId.value) { |
| | | getList(); |
| | | } |
| | | }; |
| | | // 打开弹框 |
| | | const openDialog = async (type, row) => { |
| | | operationType.value = type; |
| | | getOptions().then(res => { |
| | | supplierList.value = res.data; |
| | | }); |
| | | |
| | | const handleChangeModel = (value) => { |
| | | form.value.model = modelOptions.value.find(item => item.id == value)?.model || ''; |
| | | form.value.unit = modelOptions.value.find(item => item.id == value)?.unit || ''; |
| | | } |
| | | |
| | | const findNodeById = (nodes, productId) => { |
| | | for (let i = 0; i < nodes.length; i++) { |
| | | if (nodes[i].value === productId) { |
| | | return nodes[i].label; // 找到节点,返回该节点 |
| | | try { |
| | | const userRes = await userListNoPage(); |
| | | userList.value = userRes.data || []; |
| | | } catch (e) { |
| | | console.error("加载检验员列表失败", e); |
| | | userList.value = []; |
| | | } |
| | | if (nodes[i].children && nodes[i].children.length > 0) { |
| | | const foundNode = findNodeById(nodes[i].children, productId); |
| | | if (foundNode) { |
| | | return foundNode; // 在子节点中找到,返回该节点 |
| | | } |
| | | } |
| | | } |
| | | return null; // 没有找到节点,返回null |
| | | }; |
| | | |
| | | function convertIdToValue(data) { |
| | | return data.map((item) => { |
| | | const {id, children, ...rest} = item; |
| | | const newItem = { |
| | | ...rest, |
| | | value: id, // 将 id 改为 value |
| | | // 先重置表单数据(保持字段完整,避免弹窗首次渲染时触发必填红框“闪一下”) |
| | | form.value = { |
| | | checkTime: "", |
| | | supplier: "", |
| | | productName: "", |
| | | productId: "", |
| | | productModelId: "", |
| | | model: "", |
| | | testStandardId: "", |
| | | unit: "", |
| | | quantity: "", |
| | | checkCompany: "", |
| | | checkResult: "", |
| | | }; |
| | | if (children && children.length > 0) { |
| | | newItem.children = convertIdToValue(children); |
| | | } |
| | | |
| | | return newItem; |
| | | }); |
| | | } |
| | | |
| | | // 提交产品表单 |
| | | const submitForm = () => { |
| | | proxy.$refs.formRef.validate(valid => { |
| | | if (valid) { |
| | | form.value.inspectType = 0 |
| | | if (operationType.value === "add") { |
| | | tableData.value.forEach((item) => { |
| | | delete item.id |
| | | }) |
| | | } |
| | | const data = {...form.value, qualityInspectParams: tableData.value} |
| | | if (operationType.value === "add") { |
| | | qualityInspectAdd(data).then(res => { |
| | | proxy.$modal.msgSuccess("提交成功"); |
| | | closeDia(); |
| | | }) |
| | | } else { |
| | | qualityInspectUpdate(data).then(res => { |
| | | proxy.$modal.msgSuccess("提交成功"); |
| | | closeDia(); |
| | | }) |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | |
| | | const getList = () => { |
| | | if (!currentProductId.value) { |
| | | testStandardOptions.value = []; |
| | | tableData.value = []; |
| | | return; |
| | | } |
| | | let params = { |
| | | productId: currentProductId.value, |
| | | inspectType: 0 |
| | | } |
| | | qualityInspectDetailByProductId(params).then(res => { |
| | | // 保存下拉框选项数据 |
| | | testStandardOptions.value = res.data || []; |
| | | // 清空表格数据,等待用户选择指标 |
| | | tableData.value = []; |
| | | // 清空指标选择 |
| | | form.value.testStandardId = ''; |
| | | }) |
| | | } |
| | | // 先确保产品树已加载,否则编辑时产品/规格型号无法反显 |
| | | await getProductOptions(); |
| | | if (operationType.value === "edit") { |
| | | // 先保存 testStandardId,避免被清空 |
| | | const savedTestStandardId = row.testStandardId; |
| | | form.value = { ...row }; |
| | | currentProductId.value = row.productId || 0; |
| | | // 关键:编辑时加载规格型号下拉选项,才能反显 productModelId |
| | | if (currentProductId.value) { |
| | | try { |
| | | const res = await modelList({ id: currentProductId.value }); |
| | | modelOptions.value = res || []; |
| | | // 同步回填 model / unit(有些接口返回的 row 里可能没带全) |
| | | if (form.value.productModelId) { |
| | | handleChangeModel(form.value.productModelId); |
| | | } |
| | | } catch (e) { |
| | | console.error("加载规格型号失败", e); |
| | | modelOptions.value = []; |
| | | } |
| | | } |
| | | // 编辑模式下,先加载指标选项,然后加载参数列表 |
| | | if (currentProductId.value) { |
| | | // 先加载指标选项 |
| | | let params = { |
| | | productId: currentProductId.value, |
| | | inspectType: 0, |
| | | }; |
| | | qualityInspectDetailByProductId(params).then(res => { |
| | | testStandardOptions.value = res.data || []; |
| | | // 使用 nextTick 和 setTimeout 确保选项已经渲染到 DOM |
| | | nextTick(() => { |
| | | setTimeout(() => { |
| | | // 如果编辑数据中有 testStandardId,则设置并加载对应的参数 |
| | | if (savedTestStandardId) { |
| | | // 确保类型匹配(item.id 可能是数字或字符串) |
| | | const matchedOption = testStandardOptions.value.find( |
| | | item => |
| | | item.id == savedTestStandardId || |
| | | String(item.id) === String(savedTestStandardId) |
| | | ); |
| | | if (matchedOption) { |
| | | // 确保使用匹配项的 id(保持类型一致) |
| | | form.value.testStandardId = matchedOption.id; |
| | | // 编辑保留原检验值,直接拉取原参数数据 |
| | | getQualityInspectParamList(row.id); |
| | | } else { |
| | | // 如果找不到匹配项,尝试直接使用原值 |
| | | console.warn( |
| | | "未找到匹配的指标选项,testStandardId:", |
| | | savedTestStandardId, |
| | | "可用选项:", |
| | | testStandardOptions.value |
| | | ); |
| | | form.value.testStandardId = savedTestStandardId; |
| | | getQualityInspectParamList(row.id); |
| | | } |
| | | } else { |
| | | // 否则使用旧的逻辑 |
| | | getQualityInspectParamList(row.id); |
| | | } |
| | | }, 100); |
| | | }); |
| | | }); |
| | | } else { |
| | | getQualityInspectParamList(row.id); |
| | | } |
| | | } |
| | | // 最后再打开弹窗,并清理校验态,避免必填提示闪烁 |
| | | dialogFormVisible.value = true; |
| | | nextTick(() => { |
| | | proxy.$refs?.formRef?.clearValidate?.(); |
| | | }); |
| | | }; |
| | | const getProductOptions = () => { |
| | | return productTreeList().then(res => { |
| | | productOptions.value = convertIdToValue(res); |
| | | return productOptions.value; |
| | | }); |
| | | }; |
| | | const getModels = value => { |
| | | form.value.productModelId = undefined; |
| | | form.value.unit = undefined; |
| | | modelOptions.value = []; |
| | | currentProductId.value = value; |
| | | form.value.productName = findNodeById(productOptions.value, value); |
| | | modelList({ id: value }).then(res => { |
| | | modelOptions.value = res; |
| | | }); |
| | | if (currentProductId.value) { |
| | | getList(); |
| | | } |
| | | }; |
| | | |
| | | // 指标选择变化处理 |
| | | const handleTestStandardChange = (testStandardId) => { |
| | | if (!testStandardId) { |
| | | tableData.value = []; |
| | | return; |
| | | } |
| | | tableLoading.value = true; |
| | | getQualityTestStandardParamByTestStandardId(testStandardId).then(res => { |
| | | tableData.value = res.data || []; |
| | | }).catch(error => { |
| | | console.error('获取标准参数失败:', error); |
| | | tableData.value = []; |
| | | }).finally(() => { |
| | | tableLoading.value = false; |
| | | }) |
| | | } |
| | | const handleChangeModel = value => { |
| | | form.value.model = |
| | | modelOptions.value.find(item => item.id == value)?.model || ""; |
| | | form.value.unit = |
| | | modelOptions.value.find(item => item.id == value)?.unit || ""; |
| | | }; |
| | | |
| | | const getQualityInspectParamList = (id) => { |
| | | qualityInspectParamInfo(id).then(res => { |
| | | tableData.value = res.data; |
| | | }) |
| | | } |
| | | // 关闭弹框 |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | | tableData.value = []; |
| | | testStandardOptions.value = []; |
| | | form.value.testStandardId = ''; |
| | | dialogFormVisible.value = false; |
| | | emit('close') |
| | | }; |
| | | defineExpose({ |
| | | openDialog, |
| | | }); |
| | | const findNodeById = (nodes, productId) => { |
| | | for (let i = 0; i < nodes.length; i++) { |
| | | if (nodes[i].value === productId) { |
| | | return nodes[i].label; // 找到节点,返回该节点 |
| | | } |
| | | if (nodes[i].children && nodes[i].children.length > 0) { |
| | | const foundNode = findNodeById(nodes[i].children, productId); |
| | | if (foundNode) { |
| | | return foundNode; // 在子节点中找到,返回该节点 |
| | | } |
| | | } |
| | | } |
| | | return null; // 没有找到节点,返回null |
| | | }; |
| | | |
| | | function convertIdToValue(data) { |
| | | return data.map(item => { |
| | | const { id, children, ...rest } = item; |
| | | const newItem = { |
| | | ...rest, |
| | | value: id, // 将 id 改为 value |
| | | }; |
| | | if (children && children.length > 0) { |
| | | newItem.children = convertIdToValue(children); |
| | | } |
| | | |
| | | return newItem; |
| | | }); |
| | | } |
| | | |
| | | // 提交产品表单 |
| | | const submitForm = () => { |
| | | proxy.$refs.formRef.validate(valid => { |
| | | if (valid) { |
| | | form.value.inspectType = 0; |
| | | if (operationType.value === "add") { |
| | | tableData.value.forEach(item => { |
| | | delete item.id; |
| | | }); |
| | | } |
| | | const data = { ...form.value, qualityInspectParams: tableData.value }; |
| | | if (operationType.value === "add") { |
| | | qualityInspectAdd(data).then(res => { |
| | | proxy.$modal.msgSuccess("提交成功"); |
| | | closeDia(); |
| | | }); |
| | | } else { |
| | | qualityInspectUpdate(data).then(res => { |
| | | proxy.$modal.msgSuccess("提交成功"); |
| | | closeDia(); |
| | | }); |
| | | } |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | const getList = () => { |
| | | if (!currentProductId.value) { |
| | | testStandardOptions.value = []; |
| | | tableData.value = []; |
| | | return; |
| | | } |
| | | let params = { |
| | | productId: currentProductId.value, |
| | | inspectType: 0, |
| | | }; |
| | | qualityInspectDetailByProductId(params).then(res => { |
| | | // 保存下拉框选项数据 |
| | | testStandardOptions.value = res.data || []; |
| | | // 清空表格数据,等待用户选择指标 |
| | | tableData.value = []; |
| | | // 清空指标选择 |
| | | form.value.testStandardId = ""; |
| | | }); |
| | | }; |
| | | |
| | | // 指标选择变化处理 |
| | | const handleTestStandardChange = testStandardId => { |
| | | if (!testStandardId) { |
| | | tableData.value = []; |
| | | return; |
| | | } |
| | | tableLoading.value = true; |
| | | getQualityTestStandardParamByTestStandardId(testStandardId) |
| | | .then(res => { |
| | | tableData.value = res.data || []; |
| | | }) |
| | | .catch(error => { |
| | | console.error("获取标准参数失败:", error); |
| | | tableData.value = []; |
| | | }) |
| | | .finally(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | const getQualityInspectParamList = id => { |
| | | qualityInspectParamInfo(id).then(res => { |
| | | tableData.value = res.data; |
| | | }); |
| | | }; |
| | | |
| | | // 打开产品选择对话框 |
| | | const openProductSelectDialog = () => { |
| | | productSelectDialogVisible.value = true; |
| | | }; |
| | | |
| | | // 处理产品选择 |
| | | const handleProductSelect = products => { |
| | | if (products && products.length > 0) { |
| | | const product = products[0]; |
| | | form.value.productId = product.id; |
| | | form.value.productName = product.productName; |
| | | form.value.productModelId = product.id; |
| | | form.value.model = product.model; |
| | | form.value.unit = product.unit; |
| | | currentProductId.value = product.id; |
| | | // 加载指标选项 |
| | | getList(); |
| | | } |
| | | }; |
| | | |
| | | // 清空产品选择 |
| | | const clearProductSelection = () => { |
| | | form.value.productId = ""; |
| | | form.value.productName = ""; |
| | | form.value.productModelId = ""; |
| | | form.value.model = ""; |
| | | form.value.unit = ""; |
| | | currentProductId.value = 0; |
| | | testStandardOptions.value = []; |
| | | tableData.value = []; |
| | | form.value.testStandardId = ""; |
| | | }; |
| | | // 关闭弹框 |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | | tableData.value = []; |
| | | testStandardOptions.value = []; |
| | | form.value.testStandardId = ""; |
| | | dialogFormVisible.value = false; |
| | | emit("close"); |
| | | }; |
| | | defineExpose({ |
| | | openDialog, |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .inspection-form { |
| | | background-color: #f9f9f9; |
| | | border-radius: 8px; |
| | | padding: 20px; |
| | | margin-bottom: 20px; |
| | | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); |
| | | } |
| | | |
| | | </style> |
| | | .product-select-btn { |
| | | width: 100%; |
| | | text-align: left; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | transition: all 0.3s ease; |
| | | } |
| | | |
| | | .product-select-btn:hover { |
| | | box-shadow: 0 2px 8px rgba(0, 122, 255, 0.3); |
| | | } |
| | | |
| | | /* 增加表单项间距 */ |
| | | .el-form-item { |
| | | margin-bottom: 15px; |
| | | } |
| | | |
| | | /* 输入框和选择器的悬停效果 */ |
| | | :deep(.el-input__wrapper) { |
| | | transition: all 0.3s ease; |
| | | } |
| | | |
| | | :deep(.el-input__wrapper:hover) { |
| | | box-shadow: 0 0 0 2px rgba(0, 122, 255, 0.2) !important; |
| | | } |
| | | |
| | | :deep(.el-select) { |
| | | transition: all 0.3s ease; |
| | | } |
| | | |
| | | :deep(.el-select:hover .el-input__wrapper) { |
| | | box-shadow: 0 0 0 2px rgba(0, 122, 255, 0.2) !important; |
| | | } |
| | | |
| | | /* 日期选择器的悬停效果 */ |
| | | :deep(.el-date-picker) { |
| | | transition: all 0.3s ease; |
| | | } |
| | | |
| | | :deep(.el-date-picker:hover .el-input__wrapper) { |
| | | box-shadow: 0 0 0 2px rgba(0, 122, 255, 0.2) !important; |
| | | } |
| | | |
| | | /* 优化表格样式 */ |
| | | :deep(.el-table) { |
| | | border-radius: 8px; |
| | | overflow: hidden; |
| | | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); |
| | | transition: all 0.3s ease; |
| | | } |
| | | |
| | | :deep(.el-table:hover) { |
| | | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); |
| | | } |
| | | |
| | | :deep(.el-table th) { |
| | | background-color: #f5f7fa; |
| | | font-weight: 600; |
| | | } |
| | | |
| | | :deep(.el-table tr:hover) { |
| | | background-color: #f0f9ff; |
| | | } |
| | | |
| | | /* 表格输入框样式 */ |
| | | :deep(.el-table .el-input__wrapper) { |
| | | box-shadow: none !important; |
| | | } |
| | | |
| | | :deep(.el-table .el-input__wrapper:hover) { |
| | | box-shadow: 0 0 0 2px rgba(0, 122, 255, 0.2) !important; |
| | | } |
| | | |
| | | /* 优化对话框底部按钮 */ |
| | | .dialog-footer { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | gap: 10px; |
| | | margin-top: 20px; |
| | | } |
| | | |
| | | .dialog-footer .el-button { |
| | | transition: all 0.3s ease; |
| | | padding: 8px 20px; |
| | | border-radius: 4px; |
| | | } |
| | | |
| | | .dialog-footer .el-button:hover { |
| | | transform: translateY(-1px); |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); |
| | | } |
| | | |
| | | .dialog-footer .el-button--primary:hover { |
| | | box-shadow: 0 2px 8px rgba(0, 122, 255, 0.4); |
| | | } |
| | | |
| | | /* 表单验证状态样式 */ |
| | | :deep(.el-form-item__error) { |
| | | font-size: 12px; |
| | | color: #f56c6c; |
| | | margin-top: 4px; |
| | | } |
| | | |
| | | :deep(.el-form-item.is-error .el-input__wrapper) { |
| | | box-shadow: 0 0 0 2px rgba(245, 108, 108, 0.2) !important; |
| | | } |
| | | |
| | | :deep(.el-form-item.is-success .el-input__wrapper) { |
| | | box-shadow: 0 0 0 2px rgba(103, 194, 58, 0.2) !important; |
| | | } |
| | | |
| | | /* 响应式设计 */ |
| | | @media screen and (max-width: 1200px) { |
| | | .el-col { |
| | | :deep(.el-col) { |
| | | &[class*="el-col-8"] { |
| | | flex: 0 0 50%; |
| | | max-width: 50%; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | @media screen and (max-width: 768px) { |
| | | .el-col { |
| | | :deep(.el-col) { |
| | | &[class*="el-col-8"] { |
| | | flex: 0 0 100%; |
| | | max-width: 100%; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .inspection-form { |
| | | padding: 15px; |
| | | } |
| | | |
| | | .el-form { |
| | | label-width: 80px !important; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | flex-direction: column; |
| | | align-items: stretch; |
| | | } |
| | | |
| | | .dialog-footer .el-button { |
| | | width: 100%; |
| | | } |
| | | } |
| | | </style> |
| | |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title">供应商:</span> |
| | | <el-input |
| | | v-model="searchForm.supplier" |
| | | style="width: 240px" |
| | | placeholder="请输入供应商搜索" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | /> |
| | | <span style="margin-left: 10px" class="search_title">检测日期:</span> |
| | | <el-date-picker v-model="searchForm.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange" |
| | | placeholder="请选择" clearable @change="changeDaterange"/> |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px" |
| | | >搜索 |
| | | </el-button |
| | | > |
| | | <el-input v-model="searchForm.supplier" |
| | | style="width: 240px" |
| | | placeholder="请输入供应商搜索" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" /> |
| | | <span style="margin-left: 10px" |
| | | class="search_title">检测日期:</span> |
| | | <el-date-picker v-model="searchForm.entryDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="daterange" |
| | | placeholder="请选择" |
| | | clearable |
| | | @change="changeDaterange" /> |
| | | <el-button type="primary" |
| | | @click="handleQuery" |
| | | style="margin-left: 10px">搜索 |
| | | </el-button> |
| | | </div> |
| | | <div> |
| | | <el-button type="primary" @click="openForm('add')">新增</el-button> |
| | | <el-button type="primary" |
| | | @click="openForm('add')">新增</el-button> |
| | | <el-button @click="handleOut">导出</el-button> |
| | | <el-button type="danger" plain @click="handleDelete">删除</el-button> |
| | | <el-button type="danger" |
| | | plain |
| | | @click="handleDelete">删除</el-button> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | :total="page.total" |
| | | ></PIMTable> |
| | | <PIMTable rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | :total="page.total"></PIMTable> |
| | | </div> |
| | | <InspectionFormDia ref="inspectionFormDia" @close="handleQuery"></InspectionFormDia> |
| | | <FormDia ref="formDia" @close="handleQuery"></FormDia> |
| | | <files-dia ref="filesDia" @close="handleQuery"></files-dia> |
| | | <el-dialog v-model="dialogFormVisible" title="编辑检验员" width="30%" |
| | | <InspectionFormDia ref="inspectionFormDia" |
| | | @close="handleQuery"></InspectionFormDia> |
| | | <FormDia ref="formDia" |
| | | @close="handleQuery"></FormDia> |
| | | <files-dia ref="filesDia" |
| | | @close="handleQuery"></files-dia> |
| | | <el-dialog v-model="dialogFormVisible" |
| | | title="编辑检验员" |
| | | width="30%" |
| | | @close="closeDia"> |
| | | <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef"> |
| | | <el-form-item label="检验员:" prop="checkName"> |
| | | <el-select v-model="form.checkName" placeholder="请选择" clearable> |
| | | <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName" |
| | | :value="item.nickName"/> |
| | | <el-form :model="form" |
| | | label-width="140px" |
| | | label-position="top" |
| | | :rules="rules" |
| | | ref="formRef"> |
| | | <el-form-item label="检验员:" |
| | | prop="checkName"> |
| | | <el-select v-model="form.checkName" |
| | | placeholder="请选择" |
| | | clearable> |
| | | <el-option v-for="item in userList" |
| | | :key="item.nickName" |
| | | :label="item.nickName" |
| | | :value="item.nickName" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm">确认</el-button> |
| | | <el-button type="primary" |
| | | @click="submitForm">确认</el-button> |
| | | <el-button @click="closeDia">取消</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {Search} from "@element-plus/icons-vue"; |
| | | import {onMounted, ref, reactive, toRefs, getCurrentInstance, nextTick} from "vue"; |
| | | import InspectionFormDia from "@/views/qualityManagement/rawMaterialInspection/components/inspectionFormDia.vue"; |
| | | import FormDia from "@/views/qualityManagement/rawMaterialInspection/components/formDia.vue"; |
| | | import {ElMessageBox} from "element-plus"; |
| | | import { |
| | | downloadQualityInspect, |
| | | qualityInspectDel, |
| | | qualityInspectListPage, qualityInspectUpdate, |
| | | submitQualityInspect |
| | | } from "@/api/qualityManagement/rawMaterialInspection.js"; |
| | | import FilesDia from "@/views/qualityManagement/rawMaterialInspection/components/filesDia.vue"; |
| | | import dayjs from "dayjs"; |
| | | import {userListNoPage} from "@/api/system/user.js"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import { |
| | | onMounted, |
| | | ref, |
| | | reactive, |
| | | toRefs, |
| | | getCurrentInstance, |
| | | nextTick, |
| | | } from "vue"; |
| | | import InspectionFormDia from "@/views/qualityManagement/rawMaterialInspection/components/inspectionFormDia.vue"; |
| | | import FormDia from "@/views/qualityManagement/rawMaterialInspection/components/formDia.vue"; |
| | | import { ElMessageBox } from "element-plus"; |
| | | import { |
| | | downloadQualityInspect, |
| | | qualityInspectDel, |
| | | qualityInspectListPage, |
| | | qualityInspectUpdate, |
| | | submitQualityInspect, |
| | | } from "@/api/qualityManagement/rawMaterialInspection.js"; |
| | | import FilesDia from "@/views/qualityManagement/rawMaterialInspection/components/filesDia.vue"; |
| | | import dayjs from "dayjs"; |
| | | import { userListNoPage } from "@/api/system/user.js"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | supplier: "", |
| | | entryDate: undefined, // 录入日期 |
| | | entryDateStart: undefined, |
| | | entryDateEnd: undefined, |
| | | }, |
| | | rules: { |
| | | checkName: [{required: true, message: "请选择", trigger: "change"}], |
| | | }, |
| | | }); |
| | | const {searchForm, rules} = toRefs(data); |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "检测日期", |
| | | prop: "checkTime", |
| | | width: 120 |
| | | }, |
| | | { |
| | | label: "采购订单号", |
| | | prop: "purchaseContractNo", |
| | | width: 120 |
| | | }, |
| | | { |
| | | label: "供应商", |
| | | prop: "supplier", |
| | | width: 230 |
| | | }, |
| | | { |
| | | label: "检验员", |
| | | prop: "checkName", |
| | | }, |
| | | { |
| | | label: "产品名称", |
| | | prop: "productName", |
| | | }, |
| | | { |
| | | label: "规格型号", |
| | | prop: "model", |
| | | }, |
| | | { |
| | | label: "单位", |
| | | prop: "unit", |
| | | }, |
| | | { |
| | | label: "数量", |
| | | prop: "quantity", |
| | | width: 120 |
| | | }, |
| | | { |
| | | label: "检测单位", |
| | | prop: "checkCompany", |
| | | width: 120 |
| | | }, |
| | | { |
| | | label: "检测结果", |
| | | prop: "checkResult", |
| | | dataType: "tag", |
| | | formatType: (params) => { |
| | | if (params === '不合格') { |
| | | return "danger"; |
| | | } else if (params === '合格') { |
| | | return "success"; |
| | | } else { |
| | | return null; |
| | | } |
| | | const data = reactive({ |
| | | searchForm: { |
| | | supplier: "", |
| | | entryDate: undefined, // 录入日期 |
| | | entryDateStart: undefined, |
| | | entryDateEnd: undefined, |
| | | }, |
| | | }, |
| | | { |
| | | label: "提交状态", |
| | | prop: "inspectState", |
| | | formatData: (params) => { |
| | | if (params) { |
| | | return "已提交"; |
| | | } else { |
| | | return "未提交"; |
| | | } |
| | | rules: { |
| | | checkName: [{ required: true, message: "请选择", trigger: "change" }], |
| | | }, |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "操作", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 280, |
| | | operation: [ |
| | | { |
| | | name: "编辑", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | openForm("edit", row); |
| | | }, |
| | | disabled: (row) => { |
| | | // 已提交则禁用 |
| | | if (row.inspectState == 1) return true; |
| | | // 如果检验员有值,只有当前登录用户能编辑 |
| | | if (row.checkName) { |
| | | return row.checkName !== userStore.nickName; |
| | | } |
| | | return false; |
| | | } |
| | | }, |
| | | { |
| | | name: "附件", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | openFilesFormDia(row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "提交", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | submit(row.id); |
| | | }, |
| | | disabled: (row) => { |
| | | // 已提交则禁用 |
| | | if (row.inspectState == 1) return true; |
| | | // 如果检验员有值,只有当前登录用户能提交 |
| | | if (row.checkName) { |
| | | return row.checkName !== userStore.nickName; |
| | | } |
| | | return false; |
| | | } |
| | | }, |
| | | { |
| | | name: "分配检验员", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | if (!row.checkName) { |
| | | open(row) |
| | | } else { |
| | | proxy.$modal.msgError("检验员已存在"); |
| | | } |
| | | }, |
| | | disabled: (row) => { |
| | | return row.inspectState == 1 || row.checkName; |
| | | } |
| | | }, |
| | | { |
| | | name: "下载", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | downLoadFile(row); |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const tableLoading = ref(false); |
| | | const userList = ref([]); |
| | | const dialogFormVisible = ref(false); |
| | | const form = ref({ |
| | | checkName: "" |
| | | }); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0 |
| | | }); |
| | | const currentRow = ref(null) |
| | | const formDia = ref() |
| | | const filesDia = ref() |
| | | const inspectionFormDia = ref() |
| | | const {proxy} = getCurrentInstance() |
| | | const userStore = useUserStore() |
| | | const changeDaterange = (value) => { |
| | | searchForm.value.entryDateStart = undefined; |
| | | searchForm.value.entryDateEnd = undefined; |
| | | if (value) { |
| | | searchForm.value.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD"); |
| | | searchForm.value.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD"); |
| | | } |
| | | getList(); |
| | | }; |
| | | // 查询列表 |
| | | /** 搜索按钮操作 */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | 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 |
| | | qualityInspectListPage({...params, inspectType: 0}).then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records |
| | | page.total = res.data.total; |
| | | }).catch(err => { |
| | | tableLoading.value = false; |
| | | }) |
| | | }; |
| | | // 表格选择数据 |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | }); |
| | | const { searchForm, rules } = toRefs(data); |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "检测日期", |
| | | prop: "checkTime", |
| | | width: 150, |
| | | className: "date-cell", |
| | | }, |
| | | { |
| | | label: "供应商", |
| | | prop: "supplier", |
| | | width: 130, |
| | | }, |
| | | { |
| | | label: "检验员", |
| | | prop: "checkName", |
| | | width: 120, |
| | | className: "inspector-cell", |
| | | }, |
| | | { |
| | | label: "产品名称", |
| | | prop: "productName", |
| | | dataType: "tag", |
| | | }, |
| | | { |
| | | label: "规格型号", |
| | | prop: "model", |
| | | }, |
| | | { |
| | | label: "单位", |
| | | prop: "unit", |
| | | width: 80, |
| | | }, |
| | | { |
| | | label: "数量", |
| | | prop: "quantity", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "试样编号", |
| | | prop: "sampleCode", |
| | | width: 120, |
| | | |
| | | // 打开弹框 |
| | | const openForm = (type, row) => { |
| | | nextTick(() => { |
| | | formDia.value?.openDialog(type, row) |
| | | }) |
| | | }; |
| | | // 打开附件弹框 |
| | | const openFilesFormDia = (type, row) => { |
| | | nextTick(() => { |
| | | filesDia.value?.openDialog(type, row) |
| | | }) |
| | | }; |
| | | className: "volume-cell", |
| | | }, |
| | | { |
| | | label: "试样状态", |
| | | prop: "sampleState", |
| | | dataType: "tag", |
| | | formatType: params => { |
| | | if (params === "颗粒" || params === "固体" || params === "膏体") { |
| | | return "success"; |
| | | } else { |
| | | return "info"; |
| | | } |
| | | }, |
| | | }, |
| | | { |
| | | label: "检测性质", |
| | | prop: "inspectNature", |
| | | dataType: "tag", |
| | | formatType: params => { |
| | | if (params === "日常检验") { |
| | | return "success"; |
| | | } else if (params === "入场验收") { |
| | | return "warning"; |
| | | } else { |
| | | return null; |
| | | } |
| | | }, |
| | | }, |
| | | { |
| | | label: "取样日期", |
| | | prop: "sampleTime", |
| | | width: 150, |
| | | className: "date-cell", |
| | | }, |
| | | { |
| | | label: "检测单位", |
| | | prop: "checkCompany", |
| | | }, |
| | | { |
| | | label: "检测结果", |
| | | prop: "checkResult", |
| | | dataType: "tag", |
| | | formatType: params => { |
| | | if (params === "不合格") { |
| | | return "danger"; |
| | | } else if (params === "合格") { |
| | | return "success"; |
| | | } else { |
| | | return null; |
| | | } |
| | | }, |
| | | }, |
| | | { |
| | | label: "提交状态", |
| | | prop: "inspectState", |
| | | dataType: "tag", |
| | | formatType: params => { |
| | | if (params) { |
| | | return "success"; |
| | | } else { |
| | | return "info"; |
| | | } |
| | | }, |
| | | formatData: params => { |
| | | if (params) { |
| | | return "已提交"; |
| | | } else { |
| | | return "未提交"; |
| | | } |
| | | }, |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "操作", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 280, |
| | | operation: [ |
| | | { |
| | | name: "编辑", |
| | | type: "text", |
| | | clickFun: row => { |
| | | openForm("edit", row); |
| | | }, |
| | | disabled: row => { |
| | | // 已提交则禁用 |
| | | if (row.inspectState == 1) return true; |
| | | // 如果检验员有值,只有当前登录用户能编辑 |
| | | if (row.checkName) { |
| | | return row.checkName !== userStore.nickName; |
| | | } |
| | | return false; |
| | | }, |
| | | }, |
| | | { |
| | | name: "附件", |
| | | type: "text", |
| | | clickFun: row => { |
| | | openFilesFormDia(row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "提交", |
| | | type: "text", |
| | | clickFun: row => { |
| | | submit(row.id); |
| | | }, |
| | | disabled: row => { |
| | | // 已提交则禁用 |
| | | if (row.inspectState == 1) return true; |
| | | // 如果检验员有值,只有当前登录用户能提交 |
| | | if (row.checkName) { |
| | | return row.checkName !== userStore.nickName; |
| | | } |
| | | return false; |
| | | }, |
| | | }, |
| | | { |
| | | name: "分配检验员", |
| | | type: "text", |
| | | clickFun: row => { |
| | | if (!row.checkName) { |
| | | open(row); |
| | | } else { |
| | | proxy.$modal.msgError("检验员已存在"); |
| | | } |
| | | }, |
| | | disabled: row => { |
| | | return row.inspectState == 1 || row.checkName; |
| | | }, |
| | | }, |
| | | { |
| | | name: "下载", |
| | | type: "text", |
| | | clickFun: row => { |
| | | downLoadFile(row); |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const tableLoading = ref(false); |
| | | const userList = ref([]); |
| | | const dialogFormVisible = ref(false); |
| | | const form = ref({ |
| | | checkName: "", |
| | | }); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | const currentRow = ref(null); |
| | | const formDia = ref(); |
| | | const filesDia = ref(); |
| | | const inspectionFormDia = ref(); |
| | | const { proxy } = getCurrentInstance(); |
| | | const userStore = useUserStore(); |
| | | const changeDaterange = value => { |
| | | searchForm.value.entryDateStart = undefined; |
| | | searchForm.value.entryDateEnd = undefined; |
| | | if (value) { |
| | | searchForm.value.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD"); |
| | | searchForm.value.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD"); |
| | | } |
| | | getList(); |
| | | }; |
| | | // 查询列表 |
| | | /** 搜索按钮操作 */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | 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; |
| | | qualityInspectListPage({ ...params, inspectType: 0 }) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }) |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | // 表格选择数据 |
| | | const handleSelectionChange = selection => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | |
| | | // 删除 |
| | | const handleDelete = () => { |
| | | let ids = []; |
| | | if (selectedRows.value.length > 0) { |
| | | ids = selectedRows.value.map((item) => item.id); |
| | | } else { |
| | | proxy.$modal.msgWarning("请选择数据"); |
| | | return; |
| | | } |
| | | ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "导出", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }) |
| | | // 打开弹框 |
| | | const openForm = (type, row) => { |
| | | nextTick(() => { |
| | | formDia.value?.openDialog(type, row); |
| | | }); |
| | | }; |
| | | // 打开附件弹框 |
| | | const openFilesFormDia = (type, row) => { |
| | | nextTick(() => { |
| | | filesDia.value?.openDialog(type, row); |
| | | }); |
| | | }; |
| | | |
| | | // 删除 |
| | | const handleDelete = () => { |
| | | let ids = []; |
| | | if (selectedRows.value.length > 0) { |
| | | ids = selectedRows.value.map(item => item.id); |
| | | } else { |
| | | proxy.$modal.msgWarning("请选择数据"); |
| | | return; |
| | | } |
| | | ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "导出", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | qualityInspectDel(ids).then((res) => { |
| | | qualityInspectDel(ids).then(res => { |
| | | proxy.$modal.msgSuccess("删除成功"); |
| | | getList(); |
| | | }); |
| | |
| | | .catch(() => { |
| | | proxy.$modal.msg("已取消"); |
| | | }); |
| | | }; |
| | | // 导出 |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }) |
| | | }; |
| | | // 导出 |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/quality/qualityInspect/export", {inspectType: 0}, "原材料检验.xlsx"); |
| | | proxy.download( |
| | | "/quality/qualityInspect/export", |
| | | { inspectType: 0 }, |
| | | "原材料检验.xlsx" |
| | | ); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已取消"); |
| | | }); |
| | | }; |
| | | }; |
| | | |
| | | // 提价 |
| | | const submit = async (id) => { |
| | | const res = await submitQualityInspect({id: id}) |
| | | if (res.code === 200) { |
| | | proxy.$modal.msgSuccess("提交成功"); |
| | | getList(); |
| | | } |
| | | } |
| | | |
| | | // 关闭弹框 |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | | dialogFormVisible.value = false; |
| | | }; |
| | | |
| | | const submitForm = () => { |
| | | if (currentRow.value) { |
| | | const data = { |
| | | ...form.value, |
| | | id: currentRow.value.id |
| | | } |
| | | qualityInspectUpdate(data).then(res => { |
| | | // 提价 |
| | | const submit = async id => { |
| | | const res = await submitQualityInspect({ id: id }); |
| | | if (res.code === 200) { |
| | | proxy.$modal.msgSuccess("提交成功"); |
| | | closeDia(); |
| | | getList(); |
| | | }) |
| | | } |
| | | }; |
| | | } |
| | | }; |
| | | |
| | | const open = async (row) => { |
| | | let userLists = await userListNoPage(); |
| | | userList.value = userLists.data; |
| | | currentRow.value = row |
| | | dialogFormVisible.value = true |
| | | } |
| | | // 关闭弹框 |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | | dialogFormVisible.value = false; |
| | | }; |
| | | |
| | | const downLoadFile = (row) => { |
| | | downloadQualityInspect({ id: row.id }).then((blobData) => { |
| | | const blob = new Blob([blobData], { |
| | | type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', |
| | | }) |
| | | const downloadUrl = window.URL.createObjectURL(blob) |
| | | const submitForm = () => { |
| | | if (currentRow.value) { |
| | | const data = { |
| | | ...form.value, |
| | | id: currentRow.value.id, |
| | | }; |
| | | qualityInspectUpdate(data).then(res => { |
| | | proxy.$modal.msgSuccess("提交成功"); |
| | | closeDia(); |
| | | getList(); |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | const link = document.createElement('a') |
| | | link.href = downloadUrl |
| | | link.download = '原材料检验报告.docx' |
| | | document.body.appendChild(link) |
| | | link.click() |
| | | const open = async row => { |
| | | let userLists = await userListNoPage(); |
| | | userList.value = userLists.data; |
| | | currentRow.value = row; |
| | | dialogFormVisible.value = true; |
| | | }; |
| | | |
| | | document.body.removeChild(link) |
| | | window.URL.revokeObjectURL(downloadUrl) |
| | | }) |
| | | }; |
| | | const downLoadFile = row => { |
| | | downloadQualityInspect({ id: row.id }).then(blobData => { |
| | | const blob = new Blob([blobData], { |
| | | type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", |
| | | }); |
| | | const downloadUrl = window.URL.createObjectURL(blob); |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | const link = document.createElement("a"); |
| | | link.href = downloadUrl; |
| | | link.download = "原材料检验报告.docx"; |
| | | document.body.appendChild(link); |
| | | link.click(); |
| | | |
| | | document.body.removeChild(link); |
| | | window.URL.revokeObjectURL(downloadUrl); |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped></style> |
| | | <style scoped lang="scss"> |
| | | .app-container { |
| | | padding: 20px; |
| | | background-color: #f5f7fa; |
| | | min-height: 100vh; |
| | | } |
| | | |
| | | .search_form { |
| | | background-color: #fff; |
| | | border-radius: 8px; |
| | | padding: 20px; |
| | | margin-bottom: 20px; |
| | | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08); |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | flex-wrap: wrap; |
| | | gap: 15px; |
| | | } |
| | | |
| | | .search_form > div { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 10px; |
| | | flex-wrap: wrap; |
| | | } |
| | | |
| | | .search_title { |
| | | font-size: 14px; |
| | | color: #303133; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .table_list { |
| | | background-color: #fff; |
| | | border-radius: 8px; |
| | | padding: 20px; |
| | | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08); |
| | | } |
| | | |
| | | /* 表格样式优化 */ |
| | | :deep(.el-table) { |
| | | border-radius: 8px; |
| | | overflow: hidden; |
| | | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08); |
| | | transition: all 0.3s ease; |
| | | } |
| | | |
| | | :deep(.el-table:hover) { |
| | | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12); |
| | | } |
| | | |
| | | :deep(.el-table th) { |
| | | background-color: #f5f7fa; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | border-bottom: 2px solid #e4e7ed; |
| | | } |
| | | |
| | | :deep(.el-table td) { |
| | | border-bottom: 1px solid #ebeef5; |
| | | } |
| | | |
| | | :deep(.el-table tr:hover) { |
| | | background-color: #f0f9ff; |
| | | } |
| | | |
| | | :deep(.el-table .el-table__row) { |
| | | transition: background-color 0.3s ease; |
| | | } |
| | | |
| | | /* 表格列样式 */ |
| | | :deep(.date-cell) { |
| | | font-family: "Courier New", monospace; |
| | | color: #606266; |
| | | } |
| | | |
| | | :deep(.supplier-cell) { |
| | | font-weight: 500; |
| | | color: #303133; |
| | | } |
| | | |
| | | :deep(.inspector-cell) { |
| | | color: #409eff; |
| | | } |
| | | |
| | | :deep(.product-cell) { |
| | | font-weight: 500; |
| | | } |
| | | |
| | | :deep(.model-cell) { |
| | | color: #606266; |
| | | } |
| | | |
| | | :deep(.unit-cell) { |
| | | font-size: 12px; |
| | | color: #909399; |
| | | } |
| | | |
| | | :deep(.quantity-cell) { |
| | | font-family: "Courier New", monospace; |
| | | font-weight: 500; |
| | | color: #303133; |
| | | } |
| | | |
| | | :deep(.volume-cell) { |
| | | font-family: "Courier New", monospace; |
| | | color: #67c23a; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | :deep(.state-cell) { |
| | | font-weight: 500; |
| | | } |
| | | |
| | | :deep(.nature-cell) { |
| | | color: #606266; |
| | | } |
| | | |
| | | :deep(.company-cell) { |
| | | color: #606266; |
| | | } |
| | | |
| | | :deep(.result-cell) { |
| | | font-weight: 600; |
| | | } |
| | | |
| | | :deep(.status-cell) { |
| | | font-weight: 500; |
| | | } |
| | | |
| | | /* 按钮样式优化 */ |
| | | .el-button { |
| | | transition: all 0.3s ease; |
| | | border-radius: 4px; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .el-button:hover { |
| | | transform: translateY(-1px); |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); |
| | | } |
| | | |
| | | .el-button--primary:hover { |
| | | box-shadow: 0 2px 8px rgba(0, 122, 255, 0.4); |
| | | } |
| | | |
| | | .el-button--danger:hover { |
| | | box-shadow: 0 2px 8px rgba(245, 108, 108, 0.4); |
| | | } |
| | | |
| | | /* 输入框样式优化 */ |
| | | :deep(.el-input__wrapper) { |
| | | transition: all 0.3s ease; |
| | | border-radius: 4px; |
| | | } |
| | | |
| | | :deep(.el-input__wrapper:hover) { |
| | | box-shadow: 0 0 0 2px rgba(0, 122, 255, 0.2) !important; |
| | | } |
| | | |
| | | :deep(.el-input__wrapper.is-focus) { |
| | | box-shadow: 0 0 0 2px rgba(0, 122, 255, 0.4) !important; |
| | | } |
| | | |
| | | /* 日期选择器样式优化 */ |
| | | :deep(.el-date-editor) { |
| | | transition: all 0.3s ease; |
| | | } |
| | | |
| | | :deep(.el-date-editor:hover .el-input__wrapper) { |
| | | box-shadow: 0 0 0 2px rgba(0, 122, 255, 0.2) !important; |
| | | } |
| | | |
| | | /* 对话框样式优化 */ |
| | | :deep(.el-dialog) { |
| | | border-radius: 8px; |
| | | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); |
| | | } |
| | | |
| | | :deep(.el-dialog__header) { |
| | | background-color: #f5f7fa; |
| | | border-bottom: 1px solid #e4e7ed; |
| | | padding: 15px 20px; |
| | | margin: 0; |
| | | } |
| | | |
| | | :deep(.el-dialog__title) { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | } |
| | | |
| | | :deep(.el-dialog__body) { |
| | | padding: 20px; |
| | | } |
| | | |
| | | :deep(.el-dialog__footer) { |
| | | padding: 15px 20px; |
| | | border-top: 1px solid #e4e7ed; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | gap: 10px; |
| | | } |
| | | |
| | | /* 表单样式优化 */ |
| | | :deep(.el-form-item__label) { |
| | | font-weight: 500; |
| | | color: #606266; |
| | | } |
| | | |
| | | :deep(.el-select) { |
| | | width: 100%; |
| | | } |
| | | |
| | | /* 分页样式优化 */ |
| | | :deep(.el-pagination) { |
| | | margin-top: 20px; |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | } |
| | | |
| | | :deep(.el-pagination button) { |
| | | border-radius: 4px; |
| | | transition: all 0.3s ease; |
| | | } |
| | | |
| | | :deep(.el-pagination button:hover) { |
| | | transform: translateY(-1px); |
| | | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); |
| | | } |
| | | |
| | | /* 标签样式优化 */ |
| | | :deep(.el-tag) { |
| | | border-radius: 4px; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | :deep(.el-tag--success) { |
| | | background-color: #f0f9ff; |
| | | border-color: #b3d8ff; |
| | | color: #409eff; |
| | | } |
| | | |
| | | :deep(.el-tag--danger) { |
| | | background-color: #fef0f0; |
| | | border-color: #fbc4c4; |
| | | color: #f56c6c; |
| | | } |
| | | |
| | | /* 操作按钮样式 */ |
| | | :deep(.el-button--text) { |
| | | padding: 0 8px; |
| | | font-weight: 500; |
| | | transition: all 0.3s ease; |
| | | } |
| | | |
| | | :deep(.el-button--text:hover) { |
| | | transform: translateY(-1px); |
| | | } |
| | | |
| | | /* 响应式设计 */ |
| | | @media screen and (max-width: 1200px) { |
| | | .search_form { |
| | | flex-direction: column; |
| | | align-items: stretch; |
| | | } |
| | | |
| | | .search_form > div { |
| | | width: 100%; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .search_form > div:first-child { |
| | | flex-wrap: wrap; |
| | | } |
| | | |
| | | .search_title { |
| | | width: 100%; |
| | | margin-bottom: 8px; |
| | | } |
| | | } |
| | | |
| | | @media screen and (max-width: 768px) { |
| | | .app-container { |
| | | padding: 10px; |
| | | } |
| | | |
| | | .search_form { |
| | | padding: 15px; |
| | | } |
| | | |
| | | .table_list { |
| | | padding: 15px; |
| | | } |
| | | |
| | | .search_form > div { |
| | | flex-direction: column; |
| | | align-items: stretch; |
| | | } |
| | | |
| | | .search_form > div .el-input, |
| | | .search_form > div .el-date-picker { |
| | | width: 100% !important; |
| | | } |
| | | |
| | | .search_form > div .el-button { |
| | | width: 100%; |
| | | margin-top: 10px; |
| | | } |
| | | |
| | | :deep(.el-dialog) { |
| | | width: 90% !important; |
| | | } |
| | | |
| | | :deep(.el-table) { |
| | | font-size: 12px; |
| | | } |
| | | } |
| | | :deep(.el-table) { |
| | | .el-table__body-wrapper { |
| | | .quantity-cell, |
| | | .volume-cell, |
| | | .dimension-cell { |
| | | font-weight: 600; |
| | | color: #409eff; |
| | | font-family: "Courier New", monospace; |
| | | text-shadow: 0 1px 2px rgba(64, 158, 255, 0.2); |
| | | } |
| | | .spec-cell { |
| | | color: #67c23a; |
| | | font-weight: 500; |
| | | |
| | | padding: 4px 8px; |
| | | border-radius: 4px; |
| | | } |
| | | |
| | | .code-cell { |
| | | color: #e6a23c; |
| | | font-family: "Courier New", monospace; |
| | | font-weight: 500; |
| | | padding: 4px 8px; |
| | | border-radius: 4px; |
| | | } |
| | | } |
| | | } |
| | | </style> |