1718 lines
48 KiB
Vue
1718 lines
48 KiB
Vue
<template>
|
||
<div class="goodsinfo-page">
|
||
<el-breadcrumb separator="/" style="margin-bottom: 16px">
|
||
<el-breadcrumb-item>流程管理</el-breadcrumb-item>
|
||
<el-breadcrumb-item>样品信息管理</el-breadcrumb-item>
|
||
</el-breadcrumb>
|
||
<!-- 搜索栏 -->
|
||
<el-card class="search-card" shadow="never">
|
||
<div class="search-bar">
|
||
<el-form :inline="true" :model="queryForm" label-width="120px">
|
||
<el-form-item label="样品名称">
|
||
<el-input
|
||
v-model="queryForm.goodsName"
|
||
placeholder="输入样品名称"
|
||
clearable
|
||
style="width: 200px"
|
||
/>
|
||
</el-form-item>
|
||
<el-form-item label="样品基质类型">
|
||
<el-select
|
||
v-model="queryForm.goodsType"
|
||
placeholder="请选择样品基质类型"
|
||
clearable
|
||
filterable
|
||
style="width: 200px"
|
||
>
|
||
<el-option
|
||
v-for="option in goodsTypeOptions"
|
||
:key="option.id"
|
||
:label="option.dicValue"
|
||
:value="option.dicValue"
|
||
/>
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item label="样品状态">
|
||
<el-select
|
||
v-model="queryForm.goodsStatus"
|
||
placeholder="请选择样品状态"
|
||
clearable
|
||
style="width: 200px"
|
||
>
|
||
<el-option label="待处理" :value="0" />
|
||
<el-option label="处理成功" :value="1" />
|
||
<el-option label="处理失败" :value="4" />
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item>
|
||
<el-button type="primary" @click="handleSearch">查询</el-button>
|
||
<el-button @click="resetSearch">重置</el-button>
|
||
</el-form-item>
|
||
</el-form>
|
||
<div class="toolbar">
|
||
<el-button type="primary" @click="handleAdd">
|
||
<el-icon><Plus /></el-icon>
|
||
新增样品
|
||
</el-button>
|
||
</div>
|
||
</div>
|
||
</el-card>
|
||
|
||
<!-- 样品信息列表 -->
|
||
<el-card shadow="never">
|
||
<el-table
|
||
:data="tableData"
|
||
stripe
|
||
border
|
||
style="width: 100%"
|
||
v-loading="loading"
|
||
>
|
||
<el-table-column
|
||
type="index"
|
||
label="序号"
|
||
width="60"
|
||
:index="getIndex"
|
||
/>
|
||
<el-table-column
|
||
prop="goodsName"
|
||
label="样品名称"
|
||
min-width="150"
|
||
:formatter="formatCell"
|
||
/>
|
||
<el-table-column
|
||
prop="goodsType"
|
||
label="样品基质类型"
|
||
min-width="150"
|
||
:formatter="formatCell"
|
||
/>
|
||
<el-table-column
|
||
prop="incomeTime"
|
||
label="采样时间"
|
||
min-width="120"
|
||
:formatter="formatDate"
|
||
/>
|
||
<el-table-column
|
||
prop="goodFrom"
|
||
label="采样地点"
|
||
min-width="150"
|
||
:formatter="formatCell"
|
||
/>
|
||
<el-table-column
|
||
prop="goalDetect"
|
||
label="目标检测物"
|
||
min-width="150"
|
||
:formatter="formatCell"
|
||
/>
|
||
<el-table-column
|
||
prop="barCode"
|
||
label="条形码"
|
||
min-width="120"
|
||
:formatter="formatCell"
|
||
/>
|
||
<el-table-column
|
||
prop="goodsStatus"
|
||
label="样品状态"
|
||
width="120"
|
||
align="center"
|
||
>
|
||
<template #default="{ row }">
|
||
<el-button
|
||
:type="getStatusType(row.goodsStatus)"
|
||
link
|
||
@click="handleStatusClick(row)"
|
||
>
|
||
{{ getStatusText(row.goodsStatus) }}
|
||
</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column
|
||
label="标准流程"
|
||
width="150"
|
||
align="center"
|
||
>
|
||
<template #default="{ row }">
|
||
<el-button
|
||
:type="getFlowButtonType(row)"
|
||
link
|
||
@click="openFlowSelectDialog(row)"
|
||
>
|
||
{{ getFlowButtonText(row) }}
|
||
</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column
|
||
prop="desc"
|
||
label="描述"
|
||
min-width="150"
|
||
:formatter="formatCell"
|
||
/>
|
||
<el-table-column label="操作" width="180" fixed="right">
|
||
<template #default="scope">
|
||
<el-button type="primary" link @click="handleEdit(scope.row)">编辑</el-button>
|
||
<el-button type="danger" link @click="handleDelete(scope.row)">删除</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
<div class="pagination">
|
||
<el-pagination
|
||
v-model:current-page="pagination.pageNum"
|
||
v-model:page-size="pagination.pageSize"
|
||
:page-sizes="[10, 20, 50, 100]"
|
||
layout="total, sizes, prev, pager, next, jumper"
|
||
:total="total"
|
||
background
|
||
@current-change="handleCurrentChange"
|
||
@size-change="handleSizeChange"
|
||
/>
|
||
</div>
|
||
</el-card>
|
||
|
||
<!-- 新增/编辑抽屉 -->
|
||
<el-drawer
|
||
v-model="drawerVisible"
|
||
:title="drawerTitle"
|
||
direction="rtl"
|
||
size="600px"
|
||
:before-close="handleDrawerClose"
|
||
>
|
||
<el-form
|
||
ref="formRef"
|
||
:model="formData"
|
||
:rules="formRules"
|
||
label-width="120px"
|
||
label-position="left"
|
||
>
|
||
<el-form-item label="样品名称" prop="goodsName">
|
||
<el-input
|
||
v-model="formData.goodsName"
|
||
placeholder="请输入样品名称"
|
||
clearable
|
||
/>
|
||
</el-form-item>
|
||
<el-form-item label="样品基质类型" prop="goodsType">
|
||
<div style="display: flex; gap: 8px; width: 100%">
|
||
<el-select
|
||
v-model="formData.goodsType"
|
||
placeholder="请选择样品基质类型"
|
||
clearable
|
||
filterable
|
||
style="flex: 1"
|
||
>
|
||
<el-option
|
||
v-for="option in goodsTypeOptions"
|
||
:key="option.id"
|
||
:label="option.dicValue"
|
||
:value="option.dicValue"
|
||
/>
|
||
</el-select>
|
||
<el-button
|
||
type="success"
|
||
@click="handleConfigGoodsType"
|
||
>
|
||
<el-icon><Setting /></el-icon>
|
||
配置
|
||
</el-button>
|
||
</div>
|
||
</el-form-item>
|
||
<el-form-item label="采样时间" prop="incomeTime">
|
||
<el-date-picker
|
||
v-model="formData.incomeTime"
|
||
type="date"
|
||
placeholder="请选择采样时间"
|
||
value-format="YYYY-MM-DD"
|
||
style="width: 100%"
|
||
/>
|
||
</el-form-item>
|
||
<el-form-item label="采样地点">
|
||
<el-input
|
||
v-model="formData.goodFrom"
|
||
placeholder="请输入采样地点"
|
||
clearable
|
||
/>
|
||
</el-form-item>
|
||
<el-form-item label="目标检测物">
|
||
<el-input
|
||
v-model="formData.goalDetect"
|
||
placeholder="请输入目标检测物"
|
||
clearable
|
||
/>
|
||
</el-form-item>
|
||
<el-form-item label="条形码">
|
||
<el-input
|
||
v-model="formData.barCode"
|
||
placeholder="请输入条形码"
|
||
clearable
|
||
/>
|
||
</el-form-item>
|
||
<el-form-item label="描述">
|
||
<el-input
|
||
v-model="formData.desc"
|
||
type="textarea"
|
||
:rows="3"
|
||
placeholder="请输入描述"
|
||
clearable
|
||
/>
|
||
</el-form-item>
|
||
</el-form>
|
||
<template #footer>
|
||
<div class="drawer-footer">
|
||
<el-button @click="handleDrawerClose">取消</el-button>
|
||
<el-button type="primary" @click="handleSubmit" :loading="submitting">
|
||
确定
|
||
</el-button>
|
||
</div>
|
||
</template>
|
||
</el-drawer>
|
||
|
||
<!-- 下拉框选项配置对话框 -->
|
||
<el-dialog
|
||
v-model="selectOptionsDialogVisible"
|
||
:title="`[样品基质类型]下拉框选项列表配置`"
|
||
width="600px"
|
||
:before-close="handleSelectOptionsDialogClose"
|
||
>
|
||
<div class="select-options-container">
|
||
<!-- 输入区域 -->
|
||
<div class="select-options-input-area">
|
||
<span class="input-label">选项数据:</span>
|
||
<el-input
|
||
v-model="selectOptionInput"
|
||
placeholder="请输入选项数据"
|
||
clearable
|
||
style="flex: 1; margin-right: 8px"
|
||
@keyup.enter="handleAddSelectOption"
|
||
/>
|
||
<el-button type="primary" @click="handleAddSelectOption">添加</el-button>
|
||
</div>
|
||
|
||
<!-- 选项卡片列表 -->
|
||
<div class="select-options-cards">
|
||
<div
|
||
v-for="option in selectOptionsList"
|
||
:key="option.id"
|
||
class="select-option-card"
|
||
>
|
||
<span class="option-text">{{ option.dicValue }}</span>
|
||
<el-icon
|
||
class="option-delete-icon"
|
||
@click="handleDeleteSelectOption(option)"
|
||
>
|
||
<Close />
|
||
</el-icon>
|
||
</div>
|
||
<div v-if="selectOptionsList.length === 0" class="empty-tip">
|
||
暂无选项数据,请添加
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<template #footer>
|
||
<div class="dialog-footer">
|
||
<el-button @click="handleSelectOptionsDialogClose">取消</el-button>
|
||
<el-button type="primary" @click="handleSaveSelectOptions">保存</el-button>
|
||
</div>
|
||
</template>
|
||
</el-dialog>
|
||
|
||
<!-- 选择标准流程对话框 -->
|
||
<el-dialog
|
||
v-model="flowSelectDialogVisible"
|
||
title="选择标准流程"
|
||
width="1000px"
|
||
:close-on-click-modal="false"
|
||
:destroy-on-close="true"
|
||
>
|
||
<el-table
|
||
:data="flowSelectTableData"
|
||
stripe
|
||
border
|
||
style="width: 100%"
|
||
v-loading="flowSelectLoading"
|
||
highlight-current-row
|
||
:row-class-name="getFlowRowClassName"
|
||
>
|
||
<el-table-column
|
||
prop="flowIndex"
|
||
label="标准流程序号"
|
||
width="130"
|
||
:formatter="formatCell"
|
||
/>
|
||
<el-table-column
|
||
prop="flowName"
|
||
label="标准流程名称"
|
||
min-width="150"
|
||
:formatter="formatCell"
|
||
/>
|
||
<el-table-column
|
||
prop="busyCode"
|
||
label="业务编号"
|
||
min-width="120"
|
||
:formatter="formatCell"
|
||
/>
|
||
<el-table-column
|
||
prop="goodsCode"
|
||
label="样品编号"
|
||
min-width="120"
|
||
:formatter="formatCell"
|
||
/>
|
||
<el-table-column
|
||
prop="goodsName"
|
||
label="样品名称"
|
||
min-width="150"
|
||
:formatter="formatCell"
|
||
/>
|
||
<el-table-column
|
||
prop="checkCode"
|
||
label="检样编号"
|
||
min-width="120"
|
||
:formatter="formatCell"
|
||
/>
|
||
<el-table-column
|
||
prop="programName"
|
||
label="项目名称"
|
||
min-width="150"
|
||
:formatter="formatCell"
|
||
/>
|
||
<el-table-column
|
||
prop="testMethod"
|
||
label="检测方法"
|
||
min-width="150"
|
||
:formatter="formatCell"
|
||
/>
|
||
<el-table-column
|
||
prop="scanNum"
|
||
label="扫描编号"
|
||
min-width="120"
|
||
:formatter="formatCell"
|
||
/>
|
||
<el-table-column label="操作" width="150" fixed="right">
|
||
<template #default="{ row }">
|
||
<div style="display: flex; align-items: center; gap: 8px;">
|
||
<el-button type="success" link @click="handleChooseFlow(row)">
|
||
选择
|
||
</el-button>
|
||
<el-tag
|
||
v-if="isFlowSelected(row)"
|
||
type="success"
|
||
size="small"
|
||
effect="dark"
|
||
class="selected-tag-icon"
|
||
>
|
||
<el-icon><Check /></el-icon>
|
||
</el-tag>
|
||
</div>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
<div class="pagination">
|
||
<el-pagination
|
||
v-model:current-page="flowSelectPagination.pageNum"
|
||
v-model:page-size="flowSelectPagination.pageSize"
|
||
:page-sizes="[10, 20, 50, 100]"
|
||
layout="total, sizes, prev, pager, next, jumper"
|
||
:total="flowSelectTotal"
|
||
background
|
||
@current-change="handleFlowSelectCurrentChange"
|
||
@size-change="handleFlowSelectSizeChange"
|
||
/>
|
||
</div>
|
||
<template #footer>
|
||
<div class="dialog-footer">
|
||
<el-button @click="handleFlowSelectCancel">取消</el-button>
|
||
<el-button type="primary" @click="handleFlowSelectSave">
|
||
保存
|
||
</el-button>
|
||
</div>
|
||
</template>
|
||
</el-dialog>
|
||
|
||
<!-- 样品流程状态列表弹窗 -->
|
||
<el-dialog
|
||
v-model="flowStatusDialogVisible"
|
||
:title="flowStatusDialogTitle"
|
||
width="1200px"
|
||
:close-on-click-modal="false"
|
||
:destroy-on-close="true"
|
||
>
|
||
<el-table
|
||
:data="flowStatusTableData"
|
||
stripe
|
||
border
|
||
style="width: 100%"
|
||
v-loading="flowStatusLoading"
|
||
>
|
||
<el-table-column
|
||
type="index"
|
||
label="序号"
|
||
width="60"
|
||
:index="(index: number) => index + 1"
|
||
/>
|
||
<el-table-column
|
||
prop="islandName"
|
||
label="功能岛名称"
|
||
min-width="150"
|
||
:formatter="formatCell"
|
||
/>
|
||
<el-table-column
|
||
prop="devName"
|
||
label="设备名称"
|
||
min-width="150"
|
||
:formatter="formatCell"
|
||
/>
|
||
<el-table-column
|
||
prop="paramName"
|
||
label="参数名称"
|
||
min-width="150"
|
||
:formatter="formatCell"
|
||
/>
|
||
<el-table-column
|
||
prop="paramValue"
|
||
label="参数值"
|
||
min-width="150"
|
||
:formatter="formatCell"
|
||
/>
|
||
<el-table-column
|
||
prop="status"
|
||
label="状态"
|
||
width="100"
|
||
align="center"
|
||
>
|
||
<template #default="{ row }">
|
||
<el-tag :type="getFlowStatusType(row.status)" size="small">
|
||
{{ getFlowStatusText(row.status) }}
|
||
</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column
|
||
prop="createTime"
|
||
label="执行时间"
|
||
width="180"
|
||
:formatter="formatDateTime"
|
||
/>
|
||
</el-table>
|
||
<template #footer>
|
||
<div class="dialog-footer">
|
||
<el-button type="primary" @click="flowStatusDialogVisible = false">
|
||
关闭
|
||
</el-button>
|
||
</div>
|
||
</template>
|
||
</el-dialog>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref, reactive, onMounted } from 'vue'
|
||
import type { FormInstance, FormRules } from 'element-plus'
|
||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||
import { Plus, Setting, Close, Check } from '@element-plus/icons-vue'
|
||
import {
|
||
goodsInfoadd,
|
||
goodsInfodel,
|
||
goodsInfoupd,
|
||
goodsInfolist,
|
||
goodsInfobyid,
|
||
} from '@/api/tb/goodsinfo'
|
||
import { flowInfolist, flowInfobyid } from '@/api/tb/flowinfo'
|
||
import { dictypeadd, dictypelist } from '@/api/system/dictype'
|
||
import { dicdataadd, dicdatadel, dicdatabydicid } from '@/api/system/dicdata'
|
||
import { goodsFlowStatusselect } from '@/api/tb/goodsflowstatus'
|
||
import { islandInfobyid } from '@/api/tb/islandinfo'
|
||
import { devInfobyid } from '@/api/tb/devinfo'
|
||
import { stepInfolist } from '@/api/tb/stepinfo'
|
||
import { devparambyid } from '@/api/tb/devparam'
|
||
|
||
interface GoodsInfoItem {
|
||
id?: number | string
|
||
goodsName?: string
|
||
goodsType?: string
|
||
incomeTime?: string
|
||
goodFrom?: string
|
||
goalDetect?: string
|
||
barCode?: string
|
||
goodsStatus?: number
|
||
desc?: string
|
||
remark?: string
|
||
flowId?: number | string
|
||
flowName?: string
|
||
}
|
||
|
||
interface FlowInfoForSelect {
|
||
id?: number | string
|
||
flowIndex?: number | string
|
||
flowName?: string
|
||
busyCode?: string
|
||
goodsCode?: string
|
||
goodsName?: string
|
||
checkCode?: string
|
||
programName?: string
|
||
testMethod?: string
|
||
scanNum?: string
|
||
}
|
||
|
||
const loading = ref(false)
|
||
const submitting = ref(false)
|
||
const tableData = ref<GoodsInfoItem[]>([])
|
||
const total = ref(0)
|
||
|
||
// 查询表单
|
||
const queryForm = reactive({
|
||
goodsName: '',
|
||
goodsType: '',
|
||
goodsStatus: undefined as number | undefined,
|
||
})
|
||
|
||
// 分页
|
||
const pagination = reactive({
|
||
pageNum: 1,
|
||
pageSize: 10,
|
||
})
|
||
|
||
// 抽屉相关
|
||
const drawerVisible = ref(false)
|
||
const drawerTitle = ref('新增样品')
|
||
const isEdit = ref(false)
|
||
const formRef = ref<FormInstance>()
|
||
|
||
// 表单数据
|
||
const formData = reactive<GoodsInfoItem>({
|
||
id: undefined,
|
||
goodsName: '',
|
||
goodsType: '',
|
||
incomeTime: '',
|
||
goodFrom: '',
|
||
goalDetect: '',
|
||
barCode: '',
|
||
goodsStatus: 0, // 状态自动设置为0
|
||
desc: '',
|
||
})
|
||
|
||
// 表单验证规则
|
||
const formRules: FormRules = {
|
||
goodsName: [
|
||
{ required: true, message: '请输入样品名称', trigger: 'blur' },
|
||
],
|
||
goodsType: [
|
||
{ required: true, message: '请选择样品基质类型', trigger: 'change' },
|
||
],
|
||
incomeTime: [
|
||
{ required: true, message: '请选择采样时间', trigger: 'change' },
|
||
],
|
||
}
|
||
|
||
// 样品基质类型下拉框选项
|
||
const goodsTypeOptions = ref<any[]>([])
|
||
const goodsTypeDicId = ref<number | null>(null)
|
||
|
||
// 下拉框选项配置相关
|
||
const selectOptionsDialogVisible = ref(false)
|
||
const selectOptionInput = ref('')
|
||
const selectOptionsList = ref<any[]>([])
|
||
|
||
// 标准流程选择相关
|
||
const flowSelectDialogVisible = ref(false)
|
||
const flowSelectLoading = ref(false)
|
||
const flowSelectTableData = ref<FlowInfoForSelect[]>([])
|
||
const flowSelectTotal = ref(0)
|
||
const flowSelectPagination = reactive({
|
||
pageNum: 1,
|
||
pageSize: 10,
|
||
})
|
||
const currentGoodsForFlow = ref<GoodsInfoItem | null>(null)
|
||
const tempSelectedFlowId = ref<number | string | null>(null)
|
||
const tempSelectedFlowName = ref('')
|
||
const currentBoundFlowName = ref('')
|
||
|
||
// 样品流程状态列表相关
|
||
const flowStatusDialogVisible = ref(false)
|
||
const flowStatusDialogTitle = ref('样品流程状态列表')
|
||
const flowStatusLoading = ref(false)
|
||
const flowStatusTableData = ref<any[]>([])
|
||
const currentGoodsForStatus = ref<GoodsInfoItem | null>(null)
|
||
|
||
// 获取序号
|
||
const getIndex = (index: number) => {
|
||
return (pagination.pageNum - 1) * pagination.pageSize + index + 1
|
||
}
|
||
|
||
// 格式化单元格
|
||
const formatCell = (_row: any, _column: any, value: any) => {
|
||
if (value === 0) return 0
|
||
return value === undefined || value === null || value === '' ? '暂无' : value
|
||
}
|
||
|
||
// 格式化日期(只显示年月日)
|
||
const formatDate = (_row: any, _column: any, value: any) => {
|
||
if (!value) return '暂无'
|
||
try {
|
||
const date = new Date(value)
|
||
const year = date.getFullYear()
|
||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||
const day = String(date.getDate()).padStart(2, '0')
|
||
return `${year}-${month}-${day}`
|
||
} catch (error) {
|
||
return value
|
||
}
|
||
}
|
||
|
||
// 获取状态类型(用于按钮)
|
||
const getStatusType = (status: number | null | undefined) => {
|
||
if (status === 0) return 'primary' // 待处理 - 蓝色
|
||
if (status === 1) return 'success' // 处理成功 - 绿色
|
||
if (status === 4) return 'danger' // 处理失败 - 红色
|
||
return 'info'
|
||
}
|
||
|
||
// 获取状态文本
|
||
const getStatusText = (status: number | null | undefined) => {
|
||
if (status === 0) return '待处理'
|
||
if (status === 1) return '处理成功'
|
||
if (status === 4) return '处理失败'
|
||
return '未知'
|
||
}
|
||
|
||
// 获取标准流程按钮文本
|
||
const getFlowButtonText = (row: GoodsInfoItem) => {
|
||
const flowId = (row as any).flowId
|
||
if (flowId === undefined || flowId === null || Number(flowId) === 0) {
|
||
return '未选择'
|
||
}
|
||
// 如果flowId存在,优先显示flowName
|
||
return row.flowName || '标准流程'
|
||
}
|
||
|
||
// 获取标准流程按钮类型
|
||
const getFlowButtonType = (row: GoodsInfoItem) => {
|
||
const flowId = (row as any).flowId
|
||
if (flowId === undefined || flowId === null || Number(flowId) === 0) {
|
||
return 'warning' // 橙色
|
||
}
|
||
return 'success' // 绿色
|
||
}
|
||
|
||
// 样品状态点击事件处理
|
||
const handleStatusClick = (row: GoodsInfoItem) => {
|
||
const status = row.goodsStatus
|
||
if (status === 0) {
|
||
// 待处理 - 显示提示
|
||
ElMessage.info(`${row.goodsName || '该样品'}等待处理`)
|
||
} else if (status === 1 || status === 4) {
|
||
// 处理成功或处理失败 - 显示流程状态列表弹窗
|
||
currentGoodsForStatus.value = row
|
||
flowStatusDialogTitle.value = `${row.goodsName || '样品'}流程状态列表`
|
||
flowStatusDialogVisible.value = true
|
||
getFlowStatusList(row)
|
||
}
|
||
}
|
||
|
||
// 格式化日期时间(年月日时分秒)
|
||
const formatDateTime = (_row: any, _column: any, value: any) => {
|
||
if (!value) return '暂无'
|
||
try {
|
||
const date = new Date(value)
|
||
const year = date.getFullYear()
|
||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||
const day = String(date.getDate()).padStart(2, '0')
|
||
const hours = String(date.getHours()).padStart(2, '0')
|
||
const minutes = String(date.getMinutes()).padStart(2, '0')
|
||
const seconds = String(date.getSeconds()).padStart(2, '0')
|
||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
|
||
} catch (error) {
|
||
return value
|
||
}
|
||
}
|
||
|
||
// 获取流程状态类型
|
||
const getFlowStatusType = (status: number | null | undefined) => {
|
||
if (status === 0) return 'primary'
|
||
if (status === 1) return 'success'
|
||
if (status === 4) return 'danger'
|
||
return 'info'
|
||
}
|
||
|
||
// 获取流程状态文本
|
||
const getFlowStatusText = (status: number | null | undefined) => {
|
||
if (status === 0) return '待处理'
|
||
if (status === 1) return '处理成功'
|
||
if (status === 4) return '处理失败'
|
||
return '未知'
|
||
}
|
||
|
||
// 加载样品基质类型下拉框选项
|
||
const loadGoodsTypeOptions = async () => {
|
||
try {
|
||
// 查找或创建"样品基质类型"字典类型
|
||
const dicTypeListRes: any = await dictypelist({
|
||
pageNum: 1,
|
||
pageSize: 1000,
|
||
})
|
||
|
||
const dicTypeData = dicTypeListRes?.data ?? dicTypeListRes ?? {}
|
||
const dicTypeRecords = dicTypeData.records || dicTypeData.list || dicTypeData.rows || []
|
||
|
||
let dicType = dicTypeRecords.find(
|
||
(item: any) => item.dicName === '样品基质类型'
|
||
)
|
||
|
||
if (!dicType) {
|
||
// 如果不存在,创建新的字典类型
|
||
const dicTypeRes: any = await dictypeadd({
|
||
dicName: '样品基质类型',
|
||
})
|
||
|
||
if (dicTypeRes?.code === '0' || dicTypeRes?.code === 0 || dicTypeRes?.success) {
|
||
const newDicTypeData = dicTypeRes?.data ?? dicTypeRes ?? {}
|
||
dicType = { id: newDicTypeData.id }
|
||
|
||
// 如果返回的数据中没有ID,重新查询
|
||
if (!dicType.id) {
|
||
const refreshListRes: any = await dictypelist({
|
||
pageNum: 1,
|
||
pageSize: 1000,
|
||
})
|
||
const refreshData = refreshListRes?.data ?? refreshListRes ?? {}
|
||
const refreshRecords = refreshData.records || refreshData.list || refreshData.rows || []
|
||
const newDicType = refreshRecords.find(
|
||
(item: any) => item.dicName === '样品基质类型'
|
||
)
|
||
if (newDicType) {
|
||
dicType = newDicType
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (dicType && dicType.id) {
|
||
goodsTypeDicId.value = dicType.id
|
||
// 加载选项列表
|
||
const optionsRes: any = await dicdatabydicid(dicType.id)
|
||
const optionsData = optionsRes?.data ?? optionsRes ?? {}
|
||
const optionsRecords = Array.isArray(optionsData) ? optionsData : (optionsData.records || optionsData.list || optionsData.rows || [])
|
||
goodsTypeOptions.value = optionsRecords
|
||
}
|
||
} catch (error) {
|
||
console.error('加载样品基质类型选项失败:', error)
|
||
}
|
||
}
|
||
|
||
// 获取样品信息列表
|
||
const getGoodsInfoList = async () => {
|
||
try {
|
||
loading.value = true
|
||
const params: any = {
|
||
pageNum: pagination.pageNum,
|
||
pageSize: pagination.pageSize,
|
||
}
|
||
|
||
// 添加查询条件(过滤空值)
|
||
if (queryForm.goodsName && queryForm.goodsName.trim()) {
|
||
params.goodsName = queryForm.goodsName.trim()
|
||
}
|
||
if (queryForm.goodsType && queryForm.goodsType.trim()) {
|
||
params.goodsType = queryForm.goodsType.trim()
|
||
}
|
||
if (queryForm.goodsStatus !== undefined && queryForm.goodsStatus !== null) {
|
||
params.goodsStatus = queryForm.goodsStatus
|
||
}
|
||
|
||
const res: any = await goodsInfolist(params)
|
||
|
||
const data = res?.data ?? res ?? {}
|
||
|
||
// 兼容多种返回格式
|
||
const recordsFromData =
|
||
data.records ||
|
||
data.list ||
|
||
data.rows ||
|
||
data.items ||
|
||
(Array.isArray(data.data) ? data.data : undefined)
|
||
|
||
const records = Array.isArray(recordsFromData)
|
||
? recordsFromData
|
||
: Array.isArray(data)
|
||
? data
|
||
: []
|
||
|
||
const totalValue =
|
||
data.total ?? data.count ?? data.totalCount ?? records.length ?? 0
|
||
|
||
// 对于有flowId但没有flowName的记录,获取flowName
|
||
const recordsWithFlowName = await Promise.all(
|
||
records.map(async (record: GoodsInfoItem) => {
|
||
const flowId = (record as any).flowId
|
||
if (
|
||
flowId !== undefined &&
|
||
flowId !== null &&
|
||
Number(flowId) !== 0 &&
|
||
!record.flowName
|
||
) {
|
||
try {
|
||
const flowRes: any = await flowInfobyid(flowId)
|
||
if (flowRes.code === '0' || flowRes.code === 0) {
|
||
const flowData = flowRes.data || flowRes || {}
|
||
record.flowName = flowData.flowName || ''
|
||
}
|
||
} catch (error) {
|
||
console.error('获取标准流程名称失败:', error)
|
||
}
|
||
}
|
||
return record
|
||
})
|
||
)
|
||
|
||
tableData.value = recordsWithFlowName
|
||
total.value = Number(totalValue) || 0
|
||
} catch (error) {
|
||
console.error('获取样品信息列表失败:', error)
|
||
ElMessage.error('获取样品信息列表失败')
|
||
tableData.value = []
|
||
total.value = 0
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
|
||
// 查询
|
||
const handleSearch = () => {
|
||
pagination.pageNum = 1
|
||
getGoodsInfoList()
|
||
}
|
||
|
||
// 重置查询
|
||
const resetSearch = () => {
|
||
queryForm.goodsName = ''
|
||
queryForm.goodsType = ''
|
||
queryForm.goodsStatus = undefined
|
||
handleSearch()
|
||
}
|
||
|
||
// 分页大小改变
|
||
const handleSizeChange = (size: number) => {
|
||
pagination.pageSize = size
|
||
getGoodsInfoList()
|
||
}
|
||
|
||
// 当前页改变
|
||
const handleCurrentChange = (page: number) => {
|
||
pagination.pageNum = page
|
||
getGoodsInfoList()
|
||
}
|
||
|
||
// 重置表单
|
||
const resetForm = () => {
|
||
formData.id = undefined
|
||
formData.goodsName = ''
|
||
formData.goodsType = ''
|
||
formData.incomeTime = ''
|
||
formData.goodFrom = ''
|
||
formData.goalDetect = ''
|
||
formData.barCode = ''
|
||
formData.goodsStatus = 0
|
||
formData.desc = ''
|
||
formRef.value?.clearValidate()
|
||
}
|
||
|
||
// 打开新增抽屉
|
||
const handleAdd = () => {
|
||
isEdit.value = false
|
||
drawerTitle.value = '新增样品'
|
||
resetForm()
|
||
drawerVisible.value = true
|
||
}
|
||
|
||
// 编辑样品信息
|
||
const handleEdit = async (row: GoodsInfoItem) => {
|
||
try {
|
||
if (!row.id) {
|
||
ElMessage.warning('缺少样品信息ID')
|
||
return
|
||
}
|
||
|
||
loading.value = true
|
||
const res: any = await goodsInfobyid(row.id)
|
||
|
||
if (res.code === '0' || res.code === 0) {
|
||
const data = res.data || res || row
|
||
formData.id = data.id ?? row.id
|
||
formData.goodsName = data.goodsName ?? row.goodsName ?? ''
|
||
formData.goodsType = data.goodsType ?? row.goodsType ?? ''
|
||
// 处理日期格式
|
||
if (data.incomeTime || row.incomeTime) {
|
||
const dateValue = data.incomeTime || row.incomeTime
|
||
try {
|
||
const date = new Date(dateValue)
|
||
const year = date.getFullYear()
|
||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||
const day = String(date.getDate()).padStart(2, '0')
|
||
formData.incomeTime = `${year}-${month}-${day}`
|
||
} catch (error) {
|
||
formData.incomeTime = dateValue
|
||
}
|
||
} else {
|
||
formData.incomeTime = ''
|
||
}
|
||
formData.goodFrom = data.goodFrom ?? row.goodFrom ?? ''
|
||
formData.goalDetect = data.goalDetect ?? row.goalDetect ?? ''
|
||
formData.barCode = data.barCode ?? row.barCode ?? ''
|
||
formData.goodsStatus = data.goodsStatus ?? row.goodsStatus ?? 0
|
||
formData.desc = data.desc ?? row.desc ?? ''
|
||
|
||
isEdit.value = true
|
||
drawerTitle.value = '编辑样品'
|
||
drawerVisible.value = true
|
||
} else {
|
||
ElMessage.error(res.message || res.msg || '获取样品信息失败')
|
||
}
|
||
} catch (error) {
|
||
console.error('获取样品信息失败:', error)
|
||
ElMessage.error('获取样品信息失败')
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
|
||
// 删除样品信息
|
||
const handleDelete = async (row: GoodsInfoItem) => {
|
||
if (!row.id) {
|
||
ElMessage.warning('缺少样品信息ID')
|
||
return
|
||
}
|
||
|
||
try {
|
||
await ElMessageBox.confirm(
|
||
`确定要删除样品信息"${row.goodsName || '未命名'}"吗?`,
|
||
'提示',
|
||
{
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消',
|
||
type: 'warning',
|
||
}
|
||
)
|
||
|
||
loading.value = true
|
||
const res: any = await goodsInfodel(row.id)
|
||
|
||
if (res.code === '0' || res.code === 0) {
|
||
ElMessage.success('删除成功')
|
||
getGoodsInfoList()
|
||
} else {
|
||
ElMessage.error(res.message || res.msg || '删除失败')
|
||
}
|
||
} catch (error: any) {
|
||
if (error !== 'cancel') {
|
||
console.error('删除样品信息失败:', error)
|
||
ElMessage.error('删除样品信息失败')
|
||
}
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
|
||
// 判断某个标准流程是否被选中
|
||
const isFlowSelected = (row: FlowInfoForSelect) => {
|
||
if (!row.id || !tempSelectedFlowId.value) return false
|
||
return String(row.id) === String(tempSelectedFlowId.value)
|
||
}
|
||
|
||
// 给选中的标准流程行添加样式类
|
||
const getFlowRowClassName = ({ row }: { row: FlowInfoForSelect }) => {
|
||
if (isFlowSelected(row)) {
|
||
return 'selected-flow-row'
|
||
}
|
||
return ''
|
||
}
|
||
|
||
// 获取标准流程列表(选择弹框用)
|
||
const getFlowInfoListForSelect = async () => {
|
||
try {
|
||
flowSelectLoading.value = true
|
||
const params: any = {
|
||
pageNum: flowSelectPagination.pageNum,
|
||
pageSize: flowSelectPagination.pageSize,
|
||
}
|
||
|
||
const res: any = await flowInfolist(params)
|
||
const data = res?.data ?? res ?? {}
|
||
|
||
const recordsFromData =
|
||
data.records ||
|
||
data.list ||
|
||
data.rows ||
|
||
data.items ||
|
||
(Array.isArray(data.data) ? data.data : undefined)
|
||
|
||
const records = Array.isArray(recordsFromData)
|
||
? recordsFromData
|
||
: Array.isArray(data)
|
||
? data
|
||
: []
|
||
|
||
const totalValue =
|
||
data.total ?? data.count ?? data.totalCount ?? records.length ?? 0
|
||
|
||
flowSelectTableData.value = records
|
||
flowSelectTotal.value = Number(totalValue) || 0
|
||
} catch (error) {
|
||
console.error('获取标准流程列表失败:', error)
|
||
ElMessage.error('获取标准流程列表失败')
|
||
flowSelectTableData.value = []
|
||
flowSelectTotal.value = 0
|
||
} finally {
|
||
flowSelectLoading.value = false
|
||
}
|
||
}
|
||
|
||
// 打开标准流程选择对话框
|
||
const openFlowSelectDialog = async (row: GoodsInfoItem) => {
|
||
if (!row.id) {
|
||
ElMessage.warning('缺少样品信息ID')
|
||
return
|
||
}
|
||
|
||
currentGoodsForFlow.value = row
|
||
tempSelectedFlowId.value = null
|
||
tempSelectedFlowName.value = ''
|
||
currentBoundFlowName.value = ''
|
||
flowSelectPagination.pageNum = 1
|
||
flowSelectPagination.pageSize = 10
|
||
|
||
// 如果样品已绑定标准流程,读取已绑定流程名称并设置为选中状态
|
||
const rawFlowId = (row as any).flowId
|
||
if (rawFlowId !== undefined && rawFlowId !== null && Number(rawFlowId) !== 0) {
|
||
try {
|
||
const res: any = await flowInfobyid(rawFlowId)
|
||
if (res.code === '0' || res.code === 0) {
|
||
const data = res.data || res || {}
|
||
const flowName = data.flowName || row.flowName || ''
|
||
currentBoundFlowName.value = flowName
|
||
// 设置为已选中状态,这样打开弹框时就会显示选中效果
|
||
tempSelectedFlowId.value = rawFlowId
|
||
tempSelectedFlowName.value = flowName
|
||
}
|
||
} catch (error) {
|
||
console.error('获取已绑定标准流程信息失败:', error)
|
||
}
|
||
}
|
||
|
||
flowSelectDialogVisible.value = true
|
||
await getFlowInfoListForSelect()
|
||
}
|
||
|
||
// 标准流程分页变化(页码)
|
||
const handleFlowSelectCurrentChange = (page: number) => {
|
||
flowSelectPagination.pageNum = page
|
||
getFlowInfoListForSelect()
|
||
}
|
||
|
||
// 标准流程分页变化(每页大小)
|
||
const handleFlowSelectSizeChange = (size: number) => {
|
||
flowSelectPagination.pageSize = size
|
||
getFlowInfoListForSelect()
|
||
}
|
||
|
||
// 在弹框中选择某个标准流程
|
||
const handleChooseFlow = async (row: FlowInfoForSelect) => {
|
||
if (!row.id) {
|
||
return
|
||
}
|
||
|
||
const newFlowId = row.id
|
||
const newFlowName = row.flowName || ''
|
||
|
||
// 如果当前没有样品上下文,直接缓存
|
||
if (!currentGoodsForFlow.value) {
|
||
tempSelectedFlowId.value = newFlowId
|
||
tempSelectedFlowName.value = newFlowName
|
||
return
|
||
}
|
||
|
||
const existingFlowIdRaw = (currentGoodsForFlow.value as any).flowId
|
||
const existingFlowId =
|
||
existingFlowIdRaw === undefined || existingFlowIdRaw === null
|
||
? 0
|
||
: Number(existingFlowIdRaw)
|
||
|
||
// 如果未绑定或绑定为0,直接选择
|
||
if (!existingFlowId || existingFlowId === 0) {
|
||
tempSelectedFlowId.value = newFlowId
|
||
tempSelectedFlowName.value = newFlowName
|
||
return
|
||
}
|
||
|
||
// 如果选择的是当前已绑定的流程
|
||
if (existingFlowId === Number(newFlowId)) {
|
||
tempSelectedFlowId.value = newFlowId
|
||
tempSelectedFlowName.value = newFlowName
|
||
return
|
||
}
|
||
|
||
// 已经有绑定,选择新的需要确认
|
||
const boundName =
|
||
currentBoundFlowName.value || tempSelectedFlowName.value || '当前标准流程'
|
||
|
||
try {
|
||
await ElMessageBox.confirm(
|
||
`该样品已绑定【${boundName}】,确定换绑吗?`,
|
||
'提示',
|
||
{
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消',
|
||
type: 'warning',
|
||
}
|
||
)
|
||
tempSelectedFlowId.value = newFlowId
|
||
tempSelectedFlowName.value = newFlowName
|
||
} catch (error) {
|
||
// 取消换绑
|
||
}
|
||
}
|
||
|
||
// 取消标准流程选择(清空缓存并关闭对话框)
|
||
const handleFlowSelectCancel = () => {
|
||
tempSelectedFlowId.value = null
|
||
tempSelectedFlowName.value = ''
|
||
currentBoundFlowName.value = ''
|
||
flowSelectDialogVisible.value = false
|
||
}
|
||
|
||
// 保存标准流程选择(调用更新接口)
|
||
const handleFlowSelectSave = async () => {
|
||
if (!currentGoodsForFlow.value || !currentGoodsForFlow.value.id) {
|
||
ElMessage.warning('缺少样品信息ID,无法保存')
|
||
return
|
||
}
|
||
|
||
// 如果没有选择任何标准流程,相当于不变更,直接关闭
|
||
if (!tempSelectedFlowId.value) {
|
||
flowSelectDialogVisible.value = false
|
||
return
|
||
}
|
||
|
||
try {
|
||
const res: any = await goodsInfoupd({
|
||
id: currentGoodsForFlow.value.id,
|
||
flowId: tempSelectedFlowId.value,
|
||
})
|
||
|
||
if (res.code === '0' || res.code === 0) {
|
||
ElMessage.success('标准流程绑定成功')
|
||
|
||
// 更新当前行的flowId和flowName
|
||
if (currentGoodsForFlow.value) {
|
||
currentGoodsForFlow.value.flowId = tempSelectedFlowId.value
|
||
currentGoodsForFlow.value.flowName = tempSelectedFlowName.value
|
||
// 同时更新tableData中对应的行
|
||
const index = tableData.value.findIndex(
|
||
(item) => item.id === currentGoodsForFlow.value?.id
|
||
)
|
||
if (index !== -1 && tableData.value[index]) {
|
||
tableData.value[index].flowId = tempSelectedFlowId.value
|
||
tableData.value[index].flowName = tempSelectedFlowName.value
|
||
}
|
||
}
|
||
|
||
flowSelectDialogVisible.value = false
|
||
tempSelectedFlowId.value = null
|
||
tempSelectedFlowName.value = ''
|
||
currentBoundFlowName.value = ''
|
||
// 重新加载样品列表,刷新绑定显示
|
||
getGoodsInfoList()
|
||
} else {
|
||
ElMessage.error(res.message || res.msg || '标准流程绑定失败')
|
||
}
|
||
} catch (error) {
|
||
console.error('保存标准流程绑定失败:', error)
|
||
ElMessage.error('保存标准流程绑定失败')
|
||
}
|
||
}
|
||
|
||
|
||
// 提交表单
|
||
const handleSubmit = async () => {
|
||
if (!formRef.value) return
|
||
|
||
try {
|
||
await formRef.value.validate()
|
||
submitting.value = true
|
||
|
||
// 构建提交数据
|
||
const submitData: any = {
|
||
goodsName: formData.goodsName,
|
||
goodsType: formData.goodsType,
|
||
incomeTime: formData.incomeTime ? `${formData.incomeTime}T00:00:00` : undefined,
|
||
goodFrom: formData.goodFrom || undefined,
|
||
goalDetect: formData.goalDetect || undefined,
|
||
barCode: formData.barCode || undefined,
|
||
desc: formData.desc || undefined,
|
||
}
|
||
|
||
// 移除空字符串字段
|
||
Object.keys(submitData).forEach((key) => {
|
||
if (submitData[key] === '' || submitData[key] === null) {
|
||
delete submitData[key]
|
||
}
|
||
})
|
||
|
||
let res: any
|
||
if (isEdit.value && formData.id) {
|
||
// 编辑 - 需传入样品信息ID,其他字段可选(非空则更新)
|
||
res = await goodsInfoupd({
|
||
id: formData.id,
|
||
...submitData,
|
||
})
|
||
} else {
|
||
// 新增 - 状态自动设置为0
|
||
res = await goodsInfoadd({
|
||
...submitData,
|
||
goodsStatus: 0,
|
||
})
|
||
}
|
||
|
||
if (res.code === '0' || res.code === 0) {
|
||
ElMessage.success(isEdit.value ? '编辑成功' : '新增成功')
|
||
drawerVisible.value = false
|
||
getGoodsInfoList()
|
||
} else {
|
||
ElMessage.error(res.message || res.msg || (isEdit.value ? '编辑失败' : '新增失败'))
|
||
}
|
||
} catch (error: any) {
|
||
if (error !== false) {
|
||
console.error('提交失败:', error)
|
||
ElMessage.error('提交失败,请检查表单')
|
||
}
|
||
} finally {
|
||
submitting.value = false
|
||
}
|
||
}
|
||
|
||
// 关闭抽屉
|
||
const handleDrawerClose = () => {
|
||
drawerVisible.value = false
|
||
resetForm()
|
||
}
|
||
|
||
// 打开下拉框选项配置对话框
|
||
const handleConfigGoodsType = async () => {
|
||
try {
|
||
if (!goodsTypeDicId.value) {
|
||
// 如果字典ID不存在,先创建或查找
|
||
await loadGoodsTypeOptions()
|
||
}
|
||
|
||
if (!goodsTypeDicId.value) {
|
||
ElMessage.warning('无法获取样品基质类型字典ID')
|
||
return
|
||
}
|
||
|
||
selectOptionsDialogVisible.value = true
|
||
await loadSelectOptions(goodsTypeDicId.value)
|
||
} catch (error) {
|
||
console.error('打开下拉框配置失败:', error)
|
||
ElMessage.error('打开下拉框配置失败')
|
||
}
|
||
}
|
||
|
||
// 加载下拉框选项列表
|
||
const loadSelectOptions = async (dicId: number) => {
|
||
try {
|
||
const res: any = await dicdatabydicid(dicId)
|
||
|
||
const data = res?.data ?? res ?? {}
|
||
const records = Array.isArray(data) ? data : (data.records || data.list || data.rows || [])
|
||
|
||
selectOptionsList.value = records
|
||
} catch (error) {
|
||
console.error('加载下拉框选项失败:', error)
|
||
ElMessage.error('加载下拉框选项失败')
|
||
selectOptionsList.value = []
|
||
}
|
||
}
|
||
|
||
// 添加下拉框选项
|
||
const handleAddSelectOption = async () => {
|
||
if (!selectOptionInput.value || selectOptionInput.value.trim() === '') {
|
||
ElMessage.warning('请输入选项数据')
|
||
return
|
||
}
|
||
|
||
if (!goodsTypeDicId.value) {
|
||
ElMessage.error('字典类型ID不存在')
|
||
return
|
||
}
|
||
|
||
try {
|
||
const res: any = await dicdataadd({
|
||
dicId: goodsTypeDicId.value,
|
||
dicLabel: '样品基质类型',
|
||
dicValue: selectOptionInput.value.trim(),
|
||
})
|
||
|
||
if (res?.code === '0' || res?.code === 0 || res?.success) {
|
||
ElMessage.success('添加成功')
|
||
selectOptionInput.value = ''
|
||
// 重新加载选项列表
|
||
await loadSelectOptions(goodsTypeDicId.value)
|
||
// 重新加载下拉框选项
|
||
await loadGoodsTypeOptions()
|
||
} else {
|
||
ElMessage.error(res?.message || res?.msg || '添加失败')
|
||
}
|
||
} catch (error) {
|
||
console.error('添加下拉框选项失败:', error)
|
||
ElMessage.error('添加下拉框选项失败')
|
||
}
|
||
}
|
||
|
||
// 删除下拉框选项
|
||
const handleDeleteSelectOption = async (option: any) => {
|
||
try {
|
||
await ElMessageBox.confirm(
|
||
`确定要删除"${option.dicValue || '该选项'}"吗?`,
|
||
'提示',
|
||
{
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消',
|
||
type: 'warning',
|
||
}
|
||
)
|
||
|
||
const res: any = await dicdatadel(option.id)
|
||
|
||
if (res?.code === '0' || res?.code === 0 || res?.success) {
|
||
ElMessage.success('删除成功')
|
||
// 重新加载选项列表
|
||
if (goodsTypeDicId.value) {
|
||
await loadSelectOptions(goodsTypeDicId.value)
|
||
// 重新加载下拉框选项
|
||
await loadGoodsTypeOptions()
|
||
}
|
||
} else {
|
||
ElMessage.error(res?.message || res?.msg || '删除失败')
|
||
}
|
||
} catch (error: any) {
|
||
if (error !== 'cancel') {
|
||
console.error('删除下拉框选项失败:', error)
|
||
ElMessage.error('删除下拉框选项失败')
|
||
}
|
||
}
|
||
}
|
||
|
||
// 保存下拉框选项配置
|
||
const handleSaveSelectOptions = async () => {
|
||
if (selectOptionsList.value.length === 0) {
|
||
await ElMessageBox.alert(
|
||
'样品基质类型的下拉框选项列表还未配置,请先完成配置',
|
||
'提示',
|
||
{
|
||
confirmButtonText: '确定',
|
||
type: 'warning',
|
||
}
|
||
)
|
||
return
|
||
}
|
||
|
||
selectOptionsDialogVisible.value = false
|
||
ElMessage.success('样品基质类型下拉框选项列表保存成功!')
|
||
// 重新加载下拉框选项
|
||
await loadGoodsTypeOptions()
|
||
}
|
||
|
||
// 关闭下拉框选项配置对话框
|
||
const handleSelectOptionsDialogClose = () => {
|
||
selectOptionsDialogVisible.value = false
|
||
selectOptionInput.value = ''
|
||
selectOptionsList.value = []
|
||
}
|
||
|
||
// 获取样品流程状态列表
|
||
const getFlowStatusList = async (row: GoodsInfoItem) => {
|
||
if (!row.id) {
|
||
ElMessage.warning('缺少样品信息ID')
|
||
return
|
||
}
|
||
|
||
try {
|
||
flowStatusLoading.value = true
|
||
// 调用goodsFlowStatusselect接口,传入goodsId
|
||
const res: any = await goodsFlowStatusselect({ goodsId: row.id })
|
||
|
||
const data = res?.data ?? res ?? {}
|
||
const records = Array.isArray(data) ? data : (data.records || data.list || data.rows || [])
|
||
|
||
// 处理每条记录,查询功能岛名称、设备名称、参数名称和参数值
|
||
const processedRecords = await Promise.all(
|
||
records.map(async (record: any, index: number) => {
|
||
const processedRecord = { ...record }
|
||
|
||
// 查询功能岛名称
|
||
if (record.islandId) {
|
||
try {
|
||
const islandRes: any = await islandInfobyid(record.islandId)
|
||
if (islandRes.code === '0' || islandRes.code === 0) {
|
||
const islandData = islandRes.data || islandRes || {}
|
||
processedRecord.islandName = islandData.islandName || ''
|
||
}
|
||
} catch (error) {
|
||
console.error('获取功能岛名称失败:', error)
|
||
processedRecord.islandName = ''
|
||
}
|
||
} else {
|
||
processedRecord.islandName = ''
|
||
}
|
||
|
||
// 查询设备名称
|
||
if (record.devId) {
|
||
try {
|
||
const devRes: any = await devInfobyid(record.devId)
|
||
if (devRes.code === '0' || devRes.code === 0) {
|
||
const devData = devRes.data || devRes || {}
|
||
processedRecord.devName = devData.devName || ''
|
||
}
|
||
} catch (error) {
|
||
console.error('获取设备名称失败:', error)
|
||
processedRecord.devName = ''
|
||
}
|
||
} else {
|
||
processedRecord.devName = ''
|
||
}
|
||
|
||
// 查询参数名称和参数值(根据flowSort)
|
||
if (record.flowSort && row.flowId) {
|
||
try {
|
||
// 根据flowId和flowSort查询步骤信息
|
||
const stepRes: any = await stepInfolist({
|
||
flowId: row.flowId,
|
||
flowSort: record.flowSort,
|
||
})
|
||
const stepData = stepRes?.data ?? stepRes ?? {}
|
||
const stepRecords = Array.isArray(stepData) ? stepData : (stepData.records || stepData.list || stepData.rows || [])
|
||
|
||
if (stepRecords.length > 0) {
|
||
const stepInfo = stepRecords[0]
|
||
// 根据步骤信息中的paramId查询参数名称
|
||
if (stepInfo.paramId) {
|
||
try {
|
||
const paramRes: any = await devparambyid(stepInfo.paramId)
|
||
if (paramRes.code === '0' || paramRes.code === 0) {
|
||
const paramData = paramRes.data || paramRes || {}
|
||
processedRecord.paramName = paramData.paramName || ''
|
||
} else {
|
||
processedRecord.paramName = ''
|
||
}
|
||
} catch (error) {
|
||
console.error('获取参数名称失败:', error)
|
||
processedRecord.paramName = ''
|
||
}
|
||
} else {
|
||
processedRecord.paramName = ''
|
||
}
|
||
// 参数值从流程状态记录中获取
|
||
processedRecord.paramValue = record.paramValue || ''
|
||
} else {
|
||
processedRecord.paramName = ''
|
||
processedRecord.paramValue = record.paramValue || ''
|
||
}
|
||
} catch (error) {
|
||
console.error('获取参数信息失败:', error)
|
||
processedRecord.paramName = ''
|
||
processedRecord.paramValue = record.paramValue || ''
|
||
}
|
||
} else {
|
||
processedRecord.paramName = ''
|
||
processedRecord.paramValue = record.paramValue || ''
|
||
}
|
||
|
||
return processedRecord
|
||
})
|
||
)
|
||
|
||
flowStatusTableData.value = processedRecords
|
||
} catch (error) {
|
||
console.error('获取样品流程状态列表失败:', error)
|
||
ElMessage.error('获取样品流程状态列表失败')
|
||
flowStatusTableData.value = []
|
||
} finally {
|
||
flowStatusLoading.value = false
|
||
}
|
||
}
|
||
|
||
// 初始化
|
||
onMounted(() => {
|
||
loadGoodsTypeOptions().then(() => {
|
||
getGoodsInfoList()
|
||
})
|
||
})
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.goodsinfo-page {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 12px;
|
||
}
|
||
|
||
.search-card {
|
||
padding-bottom: 30px;
|
||
|
||
:deep(.el-card__body) {
|
||
padding: 16px 20px;
|
||
}
|
||
}
|
||
|
||
.search-bar {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
flex-wrap: wrap;
|
||
gap: 8px;
|
||
|
||
:deep(.el-form) {
|
||
margin-bottom: 0;
|
||
margin-left: -50px;
|
||
}
|
||
|
||
:deep(.el-form-item) {
|
||
margin-right: 8px;
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
:deep(.el-form-item__label) {
|
||
padding-right: 8px;
|
||
}
|
||
}
|
||
|
||
.toolbar {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
|
||
.pagination {
|
||
margin-top: 16px;
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
}
|
||
|
||
.drawer-footer {
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
gap: 10px;
|
||
}
|
||
|
||
.select-options-container {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 16px;
|
||
}
|
||
|
||
.select-options-input-area {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
|
||
.input-label {
|
||
min-width: 80px;
|
||
font-weight: 500;
|
||
font-size: 16px;
|
||
}
|
||
|
||
.select-options-cards {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 20px;
|
||
min-height: 100px;
|
||
max-height: 300px;
|
||
overflow-y: auto;
|
||
padding: 20px;
|
||
background: linear-gradient(135deg, #e3f2fd 0%, #f0f2f5 100%);
|
||
border-radius: 4px;
|
||
background-image:
|
||
linear-gradient(rgba(64, 158, 255, 0.03) 1px, transparent 1px),
|
||
linear-gradient(90deg, rgba(64, 158, 255, 0.03) 1px, transparent 1px);
|
||
background-size: 20px 20px;
|
||
}
|
||
|
||
.select-option-card {
|
||
position: relative;
|
||
padding: 16px 20px;
|
||
background-color: #fff;
|
||
border: 1px solid rgba(64, 158, 255, 0.1);
|
||
border-radius: 12px;
|
||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||
cursor: default;
|
||
transition: all 0.3s;
|
||
min-width: 120px;
|
||
font-size: 16px;
|
||
}
|
||
|
||
.select-option-card:hover {
|
||
box-shadow: 0 4px 16px rgba(64, 158, 255, 0.2);
|
||
transform: translateY(-4px);
|
||
border-color: rgba(64, 158, 255, 0.3);
|
||
}
|
||
|
||
.option-text {
|
||
font-size: 1.2em;
|
||
color: #303133;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.option-delete-icon {
|
||
position: absolute;
|
||
top: 10px;
|
||
right: 10px;
|
||
font-size: 16px;
|
||
color: #909399;
|
||
cursor: pointer;
|
||
transition: color 0.3s;
|
||
padding: 4px;
|
||
}
|
||
|
||
.option-delete-icon:hover {
|
||
color: #f56c6c;
|
||
}
|
||
|
||
.empty-tip {
|
||
width: 100%;
|
||
text-align: center;
|
||
color: #909399;
|
||
font-size: 16px;
|
||
padding: 20px 0;
|
||
}
|
||
|
||
.dialog-footer {
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
gap: 10px;
|
||
}
|
||
|
||
// 标准流程选择表格 - 选中行的样式
|
||
:deep(.selected-flow-row) {
|
||
background-color: #e8f4ff !important;
|
||
|
||
td {
|
||
background-color: #e8f4ff !important;
|
||
}
|
||
|
||
&:hover > td {
|
||
background-color: #d9ecff !important;
|
||
}
|
||
}
|
||
|
||
// 已选择标签 - 正方形小绿块样式
|
||
.selected-tag-icon {
|
||
width: 24px;
|
||
height: 24px;
|
||
padding: 0 !important;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
border-radius: 4px;
|
||
|
||
.el-icon {
|
||
margin: 0;
|
||
font-size: 14px;
|
||
}
|
||
}
|
||
</style>
|