| | |
| | | <view class="inspection-items-container"> |
| | | <view class="steps-header"> |
| | | <text class="steps-title">检验项目</text> |
| | | <text class="steps-count">共 {{ tableData.length }} 个项目</text> |
| | | <view class="steps-header-right"> |
| | | <text class="steps-count">共 {{ tableData.length }} 个项目</text> |
| | | <up-button type="primary" |
| | | size="mini" |
| | | text="追加检测项" |
| | | @click="addTempItem" /> |
| | | </view> |
| | | </view> |
| | | <view class="steps-list"> |
| | | <view v-for="(item, index) in tableData" |
| | |
| | | <view class="step-content"> |
| | | <view class="step-row"> |
| | | <text class="step-label">指标:</text> |
| | | <text class="step-value">{{ item.parameterItem }}</text> |
| | | <up-input v-if="item.isTemp" |
| | | v-model="item.parameterItem" |
| | | placeholder="请输入指标名称" |
| | | border-bottom |
| | | class="step-input" /> |
| | | <text v-else |
| | | class="step-value">{{ item.parameterItem }}</text> |
| | | </view> |
| | | <view class="step-row"> |
| | | <text class="step-label">参数类型:</text> |
| | | <view v-if="item.isTemp" |
| | | class="type-switch"> |
| | | <text class="type-option" |
| | | :class="{ active: item.parameterType === TEXT_TYPE }" |
| | | @click="setTempType(item, TEXT_TYPE)">文字</text> |
| | | <text class="type-option" |
| | | :class="{ active: item.parameterType === NUMERIC_TYPE }" |
| | | @click="setTempType(item, NUMERIC_TYPE)">数字</text> |
| | | </view> |
| | | <text v-else |
| | | class="step-value">{{ isNumeric(item) ? "数字" : "文字" }}</text> |
| | | </view> |
| | | <!-- 数字型按上下限判定,把上下限摆出来才看得懂自动判定的依据 --> |
| | | <template v-if="isNumeric(item)"> |
| | | <view class="step-row"> |
| | | <text class="step-label">最大值:</text> |
| | | <up-input v-if="item.isTemp" |
| | | v-model="item.maxValue" |
| | | type="number" |
| | | placeholder="请输入最大值" |
| | | border-bottom |
| | | class="step-input" /> |
| | | <text v-else |
| | | class="step-value">{{ item.maxValue }}</text> |
| | | </view> |
| | | <view class="step-row"> |
| | | <text class="step-label">最小值:</text> |
| | | <up-input v-if="item.isTemp" |
| | | v-model="item.minValue" |
| | | type="number" |
| | | placeholder="请输入最小值" |
| | | border-bottom |
| | | class="step-input" /> |
| | | <text v-else |
| | | class="step-value">{{ item.minValue }}</text> |
| | | </view> |
| | | </template> |
| | | <view class="step-row"> |
| | | <text class="step-label">单位:</text> |
| | | <text class="step-value">{{ item.unit }}</text> |
| | | <up-input v-if="item.isTemp" |
| | | v-model="item.unit" |
| | | placeholder="请输入单位" |
| | | border-bottom |
| | | class="step-input" /> |
| | | <text v-else |
| | | class="step-value">{{ item.unit }}</text> |
| | | </view> |
| | | <view class="step-row"> |
| | | <text class="step-label">标准值:</text> |
| | | <text class="step-value">{{ item.standardValue }}</text> |
| | | <up-input v-if="item.isTemp" |
| | | v-model="item.standardValue" |
| | | placeholder="请输入标准值" |
| | | border-bottom |
| | | class="step-input" /> |
| | | <text v-else |
| | | class="step-value">{{ item.standardValue }}</text> |
| | | </view> |
| | | <view class="step-row"> |
| | | <text class="step-label">内控值:</text> |
| | | <text class="step-value">{{ item.controlValue }}</text> |
| | | <up-input v-if="item.isTemp" |
| | | v-model="item.controlValue" |
| | | placeholder="请输入内控值" |
| | | border-bottom |
| | | class="step-input" /> |
| | | <text v-else |
| | | class="step-value">{{ item.controlValue }}</text> |
| | | </view> |
| | | <view class="step-row"> |
| | | <text class="step-label">检验值:</text> |
| | | <up-input v-model="item.testValue" |
| | | :type="isNumeric(item) ? 'number' : 'text'" |
| | | placeholder="请输入检验值" |
| | | clearable |
| | | border-bottom |
| | | class="step-input" /> |
| | | </view> |
| | | <view class="step-row"> |
| | | <text class="step-label">判定:</text> |
| | | <text class="step-value judge-text" |
| | | :class="itemPassClass(item)"> |
| | | {{ judgeText(item) }} |
| | | </text> |
| | | </view> |
| | | </view> |
| | | <view v-if="item.isTemp" |
| | | class="delete-btn" |
| | | @click="removeTempItem(index)"> |
| | | <up-icon name="close" |
| | | size="14" |
| | | color="#ffffff" /> |
| | | </view> |
| | | </view> |
| | | <view v-if="tableData.length === 0" |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, computed, onMounted, nextTick } from "vue"; |
| | | import { ref, computed, onMounted, nextTick, watch } from "vue"; |
| | | import { onShow, onLoad } from "@dcloudio/uni-app"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import dayjs from "dayjs"; |
| | |
| | | list, |
| | | } from "@/api/qualityManagement/materialInspection.js"; |
| | | import { userListNoPage } from "@/api/system/user.js"; |
| | | import { |
| | | NUMERIC_TYPE, |
| | | TEXT_TYPE, |
| | | createTempItem, |
| | | isItemPass, |
| | | judgeInspectionResult, |
| | | } from "./_utils/inspection"; |
| | | |
| | | // 显示提示信息 |
| | | const showToast = message => { |
| | |
| | | }); |
| | | }; |
| | | |
| | | // 数字型才有最大/最小值,判定也按上下限走 |
| | | const isNumeric = item => item?.parameterType === NUMERIC_TYPE; |
| | | |
| | | const judgeText = item => { |
| | | const val = item?.testValue; |
| | | if (val === null || val === undefined || val === "") return "-"; |
| | | return isItemPass(item) ? "合格" : "不合格"; |
| | | }; |
| | | |
| | | const itemPassClass = item => { |
| | | const val = item?.testValue; |
| | | if (val === null || val === undefined || val === "") return ""; |
| | | return isItemPass(item) ? "pass" : "fail"; |
| | | }; |
| | | |
| | | // 需求九.3:检验值一变就自动判定,口径见 _utils/inspection.js。 |
| | | // 与管理端一致,这里无条件覆盖 form.checkResult —— 手工选的检测结果 |
| | | // 只是临时兜底,下次改动检验项时会被重新判定覆盖。 |
| | | watch( |
| | | tableData, |
| | | rows => { |
| | | const result = judgeInspectionResult(rows); |
| | | if (result) form.value.checkResult = result; |
| | | }, |
| | | { deep: true } |
| | | ); |
| | | |
| | | // 需求九.2:临时追加检测项 |
| | | const addTempItem = () => { |
| | | tableData.value.push(createTempItem()); |
| | | }; |
| | | |
| | | const removeTempItem = index => { |
| | | tableData.value.splice(index, 1); |
| | | }; |
| | | |
| | | // 切类型时清掉不再适用的值,避免文字型残留上下限、数字型残留标准值 |
| | | const setTempType = (item, type) => { |
| | | if (item.parameterType === type) return; |
| | | item.parameterType = type; |
| | | if (type === NUMERIC_TYPE) { |
| | | item.standardValue = ""; |
| | | } else { |
| | | item.maxValue = null; |
| | | item.minValue = null; |
| | | } |
| | | }; |
| | | |
| | | // 提交表单 |
| | | const submitForm = async () => { |
| | | console.log("submitForm", form.value, tableData.value); |
| | |
| | | showToast("请选择检测结果"); |
| | | return; |
| | | } |
| | | const missingTemp = tableData.value.find( |
| | | item => item.isTemp && !item.parameterItem |
| | | ); |
| | | if (missingTemp) { |
| | | showToast("请填写追加检测项的指标名称"); |
| | | return; |
| | | } |
| | | |
| | | loading.value = true; |
| | | |
| | | form.value.inspectType = 2; |
| | | // isTemp 只是前端的行标记,不能提交给后端 |
| | | tableData.value = tableData.value.map(({ isTemp, ...rest }) => rest); |
| | | if (!isEdit.value) { |
| | | tableData.value.forEach(item => { |
| | | delete item.id; |
| | |
| | | color: #909399; |
| | | } |
| | | |
| | | .steps-header-right { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 10px; |
| | | } |
| | | |
| | | // 临时追加行的参数类型切换 |
| | | .type-switch { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .type-option { |
| | | padding: 4px 14px; |
| | | font-size: 13px; |
| | | color: #606266; |
| | | background: #f4f4f5; |
| | | border-radius: 12px; |
| | | } |
| | | |
| | | .type-option.active { |
| | | color: #409eff; |
| | | background: #ecf5ff; |
| | | } |
| | | |
| | | .judge-text.pass { |
| | | color: #67c23a; |
| | | } |
| | | |
| | | .judge-text.fail { |
| | | color: #f56c6c; |
| | | } |
| | | |
| | | .steps-list { |
| | | margin-bottom: 20px; |
| | | } |