|
|
|
|
@ -4,98 +4,133 @@
|
|
|
|
|
|
|
|
|
|
<scroll-view scroll-y class="form-scroll">
|
|
|
|
|
<view class="section-card">
|
|
|
|
|
<view class="section-title">基本信息</view>
|
|
|
|
|
<view class="section-title">{{ t('equipmentMaintenance.basicInfo') }}</view>
|
|
|
|
|
|
|
|
|
|
<view class="form-item">
|
|
|
|
|
<text class="form-label">维修单编号</text>
|
|
|
|
|
<text class="form-label">{{ t('equipmentMaintenance.repairCode') }}</text>
|
|
|
|
|
<view class="code-row">
|
|
|
|
|
<input
|
|
|
|
|
v-model="formData.repairCode"
|
|
|
|
|
class="form-input code-input"
|
|
|
|
|
type="text"
|
|
|
|
|
placeholder="请输入维修单编号"
|
|
|
|
|
:placeholder="t('equipmentMaintenance.placeholderRepairCode')"
|
|
|
|
|
:disabled="repairCodeDisabled"
|
|
|
|
|
/>
|
|
|
|
|
<view v-if="mode === 'create'" class="auto-code-wrap" @click="toggleAutoCode">
|
|
|
|
|
<text class="auto-code-text">自动生成</text>
|
|
|
|
|
<text class="auto-code-text">{{ t('equipmentMaintenance.autoCode') }}</text>
|
|
|
|
|
<switch :checked="Boolean(formData.isCode)" color="#1f4b79" @change="toggleAutoCode" />
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<view class="form-item">
|
|
|
|
|
<text class="form-label">维修单名称</text>
|
|
|
|
|
<input v-model="formData.repairName" class="form-input" type="text" placeholder="请输入维修单名称" :disabled="readonlyBase" />
|
|
|
|
|
<text class="form-label required">{{ t('equipmentMaintenance.repairName') }}</text>
|
|
|
|
|
<input v-model="formData.repairName" class="form-input" type="text" :placeholder="t('equipmentMaintenance.placeholderRepairName')" :disabled="readonlyBase" />
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<view class="form-item">
|
|
|
|
|
<text class="form-label">报修日期</text>
|
|
|
|
|
<text class="form-label required">{{ t('equipmentMaintenance.requireDate') }}</text>
|
|
|
|
|
<picker mode="date" :value="datePickerValue(formData.requireDate)" :disabled="readonlyBase" @change="(e) => onDateChange('requireDate', e)">
|
|
|
|
|
<view :class="['picker-field', !formData.requireDate ? 'is-placeholder' : '']">{{ formData.requireDate || '请选择报修日期' }}</view>
|
|
|
|
|
<view :class="['picker-field', !formData.requireDate ? 'is-placeholder' : '']">{{ formData.requireDate || t('equipmentMaintenance.placeholderRequireDate') }}</view>
|
|
|
|
|
</picker>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<view class="form-item">
|
|
|
|
|
<text class="form-label">维修人员</text>
|
|
|
|
|
<text class="form-label">{{ t('equipmentMaintenance.acceptedBy') }}</text>
|
|
|
|
|
<picker :range="userLabels" :value="acceptedByIndex" :disabled="readonlyMeta" @change="(e) => onUserChange('acceptedBy', e)">
|
|
|
|
|
<view :class="['picker-field', !formData.acceptedBy ? 'is-placeholder' : '']">{{ acceptedByLabel }}</view>
|
|
|
|
|
</picker>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<view class="form-item">
|
|
|
|
|
<text class="form-label">验收人员</text>
|
|
|
|
|
<text class="form-label">{{ t('equipmentMaintenance.confirmBy') }}</text>
|
|
|
|
|
<picker :range="userLabels" :value="confirmByIndex" :disabled="readonlyMeta" @change="(e) => onUserChange('confirmBy', e)">
|
|
|
|
|
<view :class="['picker-field', !formData.confirmBy ? 'is-placeholder' : '']">{{ confirmByLabel }}</view>
|
|
|
|
|
</picker>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<view class="form-item">
|
|
|
|
|
<view class="form-label-row">
|
|
|
|
|
<text class="form-label form-label-inline">设备</text>
|
|
|
|
|
<view v-if="!readonlyBase" class="field-scan-btn" @click="handleDeviceScan">
|
|
|
|
|
<u-icon name="scan" size="18" color="#1f4b79"></u-icon>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
<picker :range="deviceLabels" :value="deviceIndex" :disabled="readonlyBase" @change="onDeviceChange">
|
|
|
|
|
<view :class="['picker-field', !formData.deviceId ? 'is-placeholder' : '']">{{ selectedDeviceLabel }}</view>
|
|
|
|
|
</picker>
|
|
|
|
|
<view class="form-item inline-radio">
|
|
|
|
|
<text class="form-label required">{{ t('equipmentMaintenance.faultLevel') }}</text>
|
|
|
|
|
<radio-group class="radio-group" :disabled="readonlyMeta" @change="onFaultLevelChange">
|
|
|
|
|
<label v-for="item in faultLevelOptions" :key="String(item.value)" class="radio-item">
|
|
|
|
|
<radio :checked="String(formData.faultLevel || '') === String(item.value)" :disabled="readonlyMeta" :value="String(item.value)" color="#1f4b79" />
|
|
|
|
|
<text>{{ item.label }}</text>
|
|
|
|
|
</label>
|
|
|
|
|
</radio-group>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<view class="form-item inline-radio">
|
|
|
|
|
<text class="form-label">是否停机</text>
|
|
|
|
|
<text class="form-label required">{{ t('equipmentMaintenance.isShutdown') }}</text>
|
|
|
|
|
<radio-group class="radio-group" :disabled="readonlyMeta" @change="onShutdownChange">
|
|
|
|
|
<label class="radio-item">
|
|
|
|
|
<radio :checked="formData.isShutdown === true" :disabled="readonlyMeta" value="true" color="#1f4b79" />
|
|
|
|
|
<text>是</text>
|
|
|
|
|
<text>{{ t('functionCommon.yes') }}</text>
|
|
|
|
|
</label>
|
|
|
|
|
<label class="radio-item">
|
|
|
|
|
<radio :checked="formData.isShutdown === false" :disabled="readonlyMeta" value="false" color="#1f4b79" />
|
|
|
|
|
<text>否</text>
|
|
|
|
|
<text>{{ t('functionCommon.no') }}</text>
|
|
|
|
|
</label>
|
|
|
|
|
</radio-group>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<view class="form-item">
|
|
|
|
|
<text class="form-label">单据状态</text>
|
|
|
|
|
<text class="form-label">{{ t('equipmentMaintenance.status') }}</text>
|
|
|
|
|
<view class="value-field">{{ statusLabel }}</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<view class="section-card">
|
|
|
|
|
<view class="section-title">故障信息</view>
|
|
|
|
|
<view class="section-title">{{ t('equipmentMaintenance.repairObject') }}</view>
|
|
|
|
|
|
|
|
|
|
<view class="form-item inline-radio">
|
|
|
|
|
<text class="form-label">{{ t('equipmentMaintenance.machineryTypeId') }}</text>
|
|
|
|
|
<radio-group class="radio-group" :disabled="readonlyBase" @change="onMachineryTypeChange">
|
|
|
|
|
<label class="radio-item">
|
|
|
|
|
<radio :checked="Number(formData.machineryTypeId || 1) === 1" :disabled="readonlyBase" value="1" color="#1f4b79" />
|
|
|
|
|
<text>{{ t('equipmentMaintenance.machineryTypeDevice') }}</text>
|
|
|
|
|
</label>
|
|
|
|
|
<label class="radio-item">
|
|
|
|
|
<radio :checked="Number(formData.machineryTypeId || 1) === 2" :disabled="readonlyBase" value="2" color="#1f4b79" />
|
|
|
|
|
<text>{{ t('equipmentMaintenance.machineryTypeKeyItem') }}</text>
|
|
|
|
|
</label>
|
|
|
|
|
</radio-group>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<view class="form-item">
|
|
|
|
|
<view class="form-label-row">
|
|
|
|
|
<text class="form-label form-label-inline required">{{ t('equipmentMaintenance.device') }}</text>
|
|
|
|
|
<view v-if="!readonlyBase" class="field-scan-btn" @click="handleDeviceScan">
|
|
|
|
|
<u-icon name="scan" size="18" color="#1f4b79"></u-icon>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
<picker :range="deviceLabels" :value="deviceIndex" :disabled="readonlyBase" @change="onDeviceChange">
|
|
|
|
|
<view :class="['picker-field', !formData.deviceId ? 'is-placeholder' : '']">{{ selectedDeviceLabel }}</view>
|
|
|
|
|
</picker>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<view v-if="showComponentSelect" class="form-item">
|
|
|
|
|
<text class="form-label required">{{ t('equipmentMaintenance.component') }}</text>
|
|
|
|
|
<picker :range="componentLabels" :value="componentIndex" :disabled="readonlyBase" @change="onComponentChange">
|
|
|
|
|
<view :class="['picker-field', !formData.componentId ? 'is-placeholder' : '']">{{ selectedComponentLabel }}</view>
|
|
|
|
|
</picker>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<view class="section-card">
|
|
|
|
|
<view class="section-title">{{ t('equipmentMaintenance.faultInfo') }}</view>
|
|
|
|
|
|
|
|
|
|
<view class="form-item">
|
|
|
|
|
<text class="form-label required">故障现象</text>
|
|
|
|
|
<input v-model="formData.faultPhenomenon" class="form-input" type="text" placeholder="请输入故障现象" :disabled="readonlyFault" />
|
|
|
|
|
<text class="form-label required">{{ t('equipmentMaintenance.faultPhenomenon') }}</text>
|
|
|
|
|
<input v-model="formData.faultPhenomenon" class="form-input" type="text" :placeholder="t('equipmentMaintenance.placeholderFaultPhenomenon')" :disabled="readonlyFault" />
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<view class="form-item">
|
|
|
|
|
<text class="form-label">故障描述</text>
|
|
|
|
|
<textarea v-model="formData.faultDescription" class="form-textarea" :disabled="readonlyFault" maxlength="500" placeholder="请输入故障描述" />
|
|
|
|
|
<text class="form-label">{{ t('equipmentMaintenance.faultDescription') }}</text>
|
|
|
|
|
<textarea v-model="formData.faultDescription" class="form-textarea" :disabled="readonlyFault" maxlength="500" :placeholder="t('equipmentMaintenance.placeholderFaultDescription')" />
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<view class="form-item">
|
|
|
|
|
<text class="form-label">故障图片</text>
|
|
|
|
|
<text class="form-label">{{ t('equipmentMaintenance.faultImages') }}</text>
|
|
|
|
|
<view class="image-list">
|
|
|
|
|
<view v-for="(item, index) in faultImageList" :key="`${item}-${index}`" class="image-item">
|
|
|
|
|
<image class="preview-image" :src="item" mode="aspectFill" @click="previewImages(faultImageList, index)" />
|
|
|
|
|
@ -109,63 +144,63 @@
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<view v-if="showRepairSection" class="section-card">
|
|
|
|
|
<view class="section-title">处理结果</view>
|
|
|
|
|
<view class="section-title">{{ t('equipmentMaintenance.repairResultSection') }}</view>
|
|
|
|
|
|
|
|
|
|
<view class="form-item inline-radio">
|
|
|
|
|
<text class="form-label required">维修结果</text>
|
|
|
|
|
<text class="form-label required">{{ t('equipmentMaintenance.repairResult') }}</text>
|
|
|
|
|
<radio-group class="radio-group" :disabled="readonlyRepair" @change="onRepairStatusChange">
|
|
|
|
|
<label class="radio-item">
|
|
|
|
|
<radio :checked="String(formData.repairStatus || '0') === '1'" :disabled="readonlyRepair" value="1" color="#1f4b79" />
|
|
|
|
|
<text>通过</text>
|
|
|
|
|
<text>{{ t('equipmentMaintenance.statusPassed') }}</text>
|
|
|
|
|
</label>
|
|
|
|
|
<label class="radio-item">
|
|
|
|
|
<radio :checked="String(formData.repairStatus || '0') === '2'" :disabled="readonlyRepair" value="2" color="#1f4b79" />
|
|
|
|
|
<text>不通过</text>
|
|
|
|
|
<text>{{ t('equipmentMaintenance.statusRejected') }}</text>
|
|
|
|
|
</label>
|
|
|
|
|
</radio-group>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<view class="form-item">
|
|
|
|
|
<text class="form-label required">完成日期</text>
|
|
|
|
|
<text class="form-label required">{{ t('equipmentMaintenance.finishDate') }}</text>
|
|
|
|
|
<picker mode="date" :value="datePickerValue(formData.finishDate)" :disabled="readonlyRepair" @change="(e) => onDateChange('finishDate', e)">
|
|
|
|
|
<view :class="['picker-field', !formData.finishDate ? 'is-placeholder' : '']">{{ formData.finishDate || '请选择完成日期' }}</view>
|
|
|
|
|
<view :class="['picker-field', !formData.finishDate ? 'is-placeholder' : '']">{{ formData.finishDate || t('equipmentMaintenance.placeholderFinishDate') }}</view>
|
|
|
|
|
</picker>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<view class="form-item">
|
|
|
|
|
<text class="form-label required">验收日期</text>
|
|
|
|
|
<text class="form-label required">{{ t('equipmentMaintenance.confirmDate') }}</text>
|
|
|
|
|
<picker mode="date" :value="datePickerValue(formData.confirmDate)" :disabled="readonlyRepair" @change="(e) => onDateChange('confirmDate', e)">
|
|
|
|
|
<view :class="['picker-field', !formData.confirmDate ? 'is-placeholder' : '']">{{ formData.confirmDate || '请选择验收日期' }}</view>
|
|
|
|
|
<view :class="['picker-field', !formData.confirmDate ? 'is-placeholder' : '']">{{ formData.confirmDate || t('equipmentMaintenance.placeholderConfirmDate') }}</view>
|
|
|
|
|
</picker>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<view class="form-item">
|
|
|
|
|
<text class="form-label">停机时长</text>
|
|
|
|
|
<input v-model="formData.downtimeDuration" class="form-input" type="digit" placeholder="请输入停机时长,单位小时" :disabled="readonlyRepair" />
|
|
|
|
|
<text class="form-label">{{ t('equipmentMaintenance.downtimeDuration') }}</text>
|
|
|
|
|
<input v-model="formData.downtimeDuration" class="form-input" type="digit" :placeholder="t('equipmentMaintenance.placeholderDowntimeDuration')" :disabled="readonlyRepair" />
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<view class="form-item">
|
|
|
|
|
<text class="form-label">故障原因</text>
|
|
|
|
|
<input v-model="formData.faultReason" class="form-input" type="text" placeholder="请输入故障原因" :disabled="readonlyRepair" />
|
|
|
|
|
<text class="form-label">{{ t('equipmentMaintenance.faultReason') }}</text>
|
|
|
|
|
<input v-model="formData.faultReason" class="form-input" type="text" :placeholder="t('equipmentMaintenance.placeholderFaultReason')" :disabled="readonlyRepair" />
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<view class="form-item">
|
|
|
|
|
<text class="form-label">处理措施</text>
|
|
|
|
|
<input v-model="formData.handlingMeasures" class="form-input" type="text" placeholder="请输入处理措施" :disabled="readonlyRepair" />
|
|
|
|
|
<text class="form-label">{{ t('equipmentMaintenance.handlingMeasures') }}</text>
|
|
|
|
|
<input v-model="formData.handlingMeasures" class="form-input" type="text" :placeholder="t('equipmentMaintenance.placeholderHandlingMeasures')" :disabled="readonlyRepair" />
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<view class="form-item">
|
|
|
|
|
<text class="form-label">更换配件</text>
|
|
|
|
|
<input v-model="formData.replacementParts" class="form-input" type="text" placeholder="请输入更换配件" :disabled="readonlyRepair" />
|
|
|
|
|
<text class="form-label">{{ t('equipmentMaintenance.replacementParts') }}</text>
|
|
|
|
|
<input v-model="formData.replacementParts" class="form-input" type="text" :placeholder="t('equipmentMaintenance.placeholderReplacementParts')" :disabled="readonlyRepair" />
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<view class="form-item">
|
|
|
|
|
<text class="form-label">维修内容</text>
|
|
|
|
|
<textarea v-model="formData.repairContent" class="form-textarea" :disabled="readonlyRepair" maxlength="1000" placeholder="请输入维修内容" />
|
|
|
|
|
<text class="form-label">{{ t('equipmentMaintenance.repairContent') }}</text>
|
|
|
|
|
<textarea v-model="formData.repairContent" class="form-textarea" :disabled="readonlyRepair" maxlength="1000" :placeholder="t('equipmentMaintenance.placeholderRepairContent')" />
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<view class="form-item">
|
|
|
|
|
<text class="form-label">维修后图片</text>
|
|
|
|
|
<text class="form-label">{{ t('equipmentMaintenance.repairedImages') }}</text>
|
|
|
|
|
<view class="image-list">
|
|
|
|
|
<view v-for="(item, index) in repairedImageList" :key="`${item}-${index}`" class="image-item">
|
|
|
|
|
<image class="preview-image" :src="item" mode="aspectFill" @click="previewImages(repairedImageList, index)" />
|
|
|
|
|
@ -179,15 +214,15 @@
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<view class="section-card last-section">
|
|
|
|
|
<view class="section-title">备注</view>
|
|
|
|
|
<view class="section-title">{{ t('equipmentMaintenance.remark') }}</view>
|
|
|
|
|
<view class="form-item no-border">
|
|
|
|
|
<textarea v-model="formData.remark" class="form-textarea" :disabled="isReadonly" maxlength="300" placeholder="请输入备注" />
|
|
|
|
|
<textarea v-model="formData.remark" class="form-textarea" :disabled="isReadonly" maxlength="300" :placeholder="t('equipmentMaintenance.placeholderRemark')" />
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</scroll-view>
|
|
|
|
|
|
|
|
|
|
<view class="page-footer">
|
|
|
|
|
<view class="footer-btn cancel" @click="goBack">返回</view>
|
|
|
|
|
<view class="footer-btn cancel" @click="goBack">{{ t('dashboard.back') }}</view>
|
|
|
|
|
<view v-if="!isReadonly" class="footer-btn confirm" @click="submitForm">{{ submitButtonText }}</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
@ -196,6 +231,7 @@
|
|
|
|
|
<script setup>
|
|
|
|
|
import { computed, reactive, ref } from 'vue'
|
|
|
|
|
import { onLoad } from '@dcloudio/uni-app'
|
|
|
|
|
import { useI18n } from 'vue-i18n'
|
|
|
|
|
import NavBar from '@/components/common/NavBar.vue'
|
|
|
|
|
import { getDeviceLedgerList } from '@/api/mes/deviceLedger'
|
|
|
|
|
import {
|
|
|
|
|
@ -205,12 +241,18 @@ import {
|
|
|
|
|
updateDvRepairStatus,
|
|
|
|
|
uploadRepairImage
|
|
|
|
|
} from '@/api/mes/dvrepair'
|
|
|
|
|
import { getCriticalComponentList } from '@/api/mes/criticalComponent'
|
|
|
|
|
import { getSimpleUserList } from '@/api/system/user'
|
|
|
|
|
import { DICT_TYPE, initAllDict } from '@/utils/dict'
|
|
|
|
|
import useDictStore from '@/store/modules/dict'
|
|
|
|
|
|
|
|
|
|
const { t } = useI18n()
|
|
|
|
|
const dictStore = useDictStore()
|
|
|
|
|
const mode = ref('create')
|
|
|
|
|
const repairId = ref('')
|
|
|
|
|
const users = ref([])
|
|
|
|
|
const deviceOptions = ref([])
|
|
|
|
|
const componentOptions = ref([])
|
|
|
|
|
const loading = ref(false)
|
|
|
|
|
|
|
|
|
|
const formData = reactive({
|
|
|
|
|
@ -219,6 +261,7 @@ const formData = reactive({
|
|
|
|
|
repairName: '',
|
|
|
|
|
isCode: true,
|
|
|
|
|
deviceId: undefined,
|
|
|
|
|
componentId: undefined,
|
|
|
|
|
machineryId: undefined,
|
|
|
|
|
machineryCode: '',
|
|
|
|
|
machineryName: '',
|
|
|
|
|
@ -232,6 +275,7 @@ const formData = reactive({
|
|
|
|
|
repairResult: '0',
|
|
|
|
|
acceptedBy: '',
|
|
|
|
|
confirmBy: '',
|
|
|
|
|
faultLevel: '',
|
|
|
|
|
isShutdown: undefined,
|
|
|
|
|
status: '0',
|
|
|
|
|
faultPhenomenon: '',
|
|
|
|
|
@ -247,10 +291,10 @@ const formData = reactive({
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const pageTitle = computed(() => {
|
|
|
|
|
if (mode.value === 'repair') return '维修处理'
|
|
|
|
|
if (mode.value === 'update') return '编辑设备维修'
|
|
|
|
|
if (mode.value === 'detail') return '设备维修详情'
|
|
|
|
|
return '新增设备维修'
|
|
|
|
|
if (mode.value === 'repair') return t('equipmentMaintenance.repairTitle')
|
|
|
|
|
if (mode.value === 'update') return t('equipmentMaintenance.editTitle')
|
|
|
|
|
if (mode.value === 'detail') return t('equipmentMaintenance.detailTitle')
|
|
|
|
|
return t('equipmentMaintenance.createTitle')
|
|
|
|
|
})
|
|
|
|
|
const isReadonly = computed(() => mode.value === 'detail')
|
|
|
|
|
const readonlyBase = computed(() => mode.value === 'repair' || mode.value === 'detail')
|
|
|
|
|
@ -259,26 +303,52 @@ const readonlyFault = computed(() => mode.value === 'repair' || mode.value === '
|
|
|
|
|
const readonlyRepair = computed(() => mode.value !== 'repair')
|
|
|
|
|
const repairCodeDisabled = computed(() => Boolean(formData.isCode) || mode.value !== 'create')
|
|
|
|
|
const showRepairSection = computed(() => mode.value === 'repair' || mode.value === 'detail' || String(formData.repairStatus || '0') !== '0' || String(formData.status || '0') === '1')
|
|
|
|
|
const submitButtonText = computed(() => '保存')
|
|
|
|
|
const submitButtonText = computed(() => t('functionCommon.save'))
|
|
|
|
|
const statusLabel = computed(() => {
|
|
|
|
|
const normalized = String(formData.repairStatus || '0')
|
|
|
|
|
if (normalized === '1') return '通过'
|
|
|
|
|
if (normalized === '2') return '不通过'
|
|
|
|
|
return '待维修'
|
|
|
|
|
if (normalized === '1') return t('equipmentMaintenance.statusPassed')
|
|
|
|
|
if (normalized === '2') return t('equipmentMaintenance.statusRejected')
|
|
|
|
|
return t('equipmentMaintenance.statusPending')
|
|
|
|
|
})
|
|
|
|
|
const userLabels = computed(() => users.value.map((item) => item.nickname || item.name || String(item.id || '')))
|
|
|
|
|
const deviceLabels = computed(() => deviceOptions.value.map((item) => item.label))
|
|
|
|
|
const faultLevelOptions = computed(() => {
|
|
|
|
|
const dicts = dictStore.getDict(DICT_TYPE.FAILURE_LEVEL) || []
|
|
|
|
|
return dicts
|
|
|
|
|
.filter((item) => item?.value !== null && item?.value !== undefined && String(item.value) !== '')
|
|
|
|
|
.map((item) => ({
|
|
|
|
|
label: item.label,
|
|
|
|
|
value: String(item.value)
|
|
|
|
|
}))
|
|
|
|
|
})
|
|
|
|
|
const acceptedByIndex = computed(() => findUserIndex(formData.acceptedBy))
|
|
|
|
|
const confirmByIndex = computed(() => findUserIndex(formData.confirmBy))
|
|
|
|
|
const acceptedByLabel = computed(() => resolveUserLabel(formData.acceptedBy, '请选择维修人员'))
|
|
|
|
|
const confirmByLabel = computed(() => resolveUserLabel(formData.confirmBy, '请选择验收人员'))
|
|
|
|
|
const acceptedByLabel = computed(() => resolveUserLabel(formData.acceptedBy, t('equipmentMaintenance.placeholderAcceptedBy')))
|
|
|
|
|
const confirmByLabel = computed(() => resolveUserLabel(formData.confirmBy, t('equipmentMaintenance.placeholderConfirmBy')))
|
|
|
|
|
const showComponentSelect = computed(() => Number(formData.machineryTypeId || 1) === 2)
|
|
|
|
|
const deviceIndex = computed(() => {
|
|
|
|
|
const index = deviceOptions.value.findIndex((item) => String(item.value) === String(formData.deviceId || ''))
|
|
|
|
|
return index >= 0 ? index : 0
|
|
|
|
|
})
|
|
|
|
|
const selectedDeviceLabel = computed(() => {
|
|
|
|
|
const current = deviceOptions.value.find((item) => String(item.value) === String(formData.deviceId || ''))
|
|
|
|
|
return current?.label || '请选择设备'
|
|
|
|
|
return current?.label || t('equipmentMaintenance.placeholderDevice')
|
|
|
|
|
})
|
|
|
|
|
const filteredComponentOptions = computed(() => {
|
|
|
|
|
const source = Array.isArray(componentOptions.value) ? componentOptions.value : []
|
|
|
|
|
const currentDeviceId = String(formData.deviceId || '').trim()
|
|
|
|
|
if (!currentDeviceId) return source
|
|
|
|
|
const matched = source.filter((item) => matchesComponentDevice(item?.raw, currentDeviceId))
|
|
|
|
|
return matched.length ? matched : source
|
|
|
|
|
})
|
|
|
|
|
const componentLabels = computed(() => filteredComponentOptions.value.map((item) => item.label))
|
|
|
|
|
const componentIndex = computed(() => {
|
|
|
|
|
const index = filteredComponentOptions.value.findIndex((item) => String(item.value) === String(formData.componentId || ''))
|
|
|
|
|
return index >= 0 ? index : 0
|
|
|
|
|
})
|
|
|
|
|
const selectedComponentLabel = computed(() => {
|
|
|
|
|
const current = filteredComponentOptions.value.find((item) => String(item.value) === String(formData.componentId || ''))
|
|
|
|
|
return current?.label || t('equipmentMaintenance.placeholderComponent')
|
|
|
|
|
})
|
|
|
|
|
const faultImageList = computed(() => splitImages(formData.faultImages))
|
|
|
|
|
const repairedImageList = computed(() => splitImages(formData.repairedImages))
|
|
|
|
|
@ -286,7 +356,8 @@ const repairedImageList = computed(() => splitImages(formData.repairedImages))
|
|
|
|
|
onLoad(async (options) => {
|
|
|
|
|
mode.value = String(options?.mode || 'create')
|
|
|
|
|
repairId.value = String(options?.id || '')
|
|
|
|
|
await Promise.all([fetchUsers(), fetchDevices()])
|
|
|
|
|
await initAllDict()
|
|
|
|
|
await Promise.all([fetchUsers(), fetchDevices(), fetchComponents()])
|
|
|
|
|
if (repairId.value) {
|
|
|
|
|
await fetchDetail(repairId.value)
|
|
|
|
|
}
|
|
|
|
|
@ -320,6 +391,23 @@ async function fetchDevices() {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function fetchComponents() {
|
|
|
|
|
try {
|
|
|
|
|
const res = await getCriticalComponentList()
|
|
|
|
|
const root = res && res.data !== undefined ? res.data : res
|
|
|
|
|
const data = Array.isArray(root) ? root : (Array.isArray(root?.data) ? root.data : [])
|
|
|
|
|
componentOptions.value = (Array.isArray(data) ? data : [])
|
|
|
|
|
.filter((item) => item && item.id !== undefined && item.id !== null)
|
|
|
|
|
.map((item) => ({
|
|
|
|
|
value: item.id,
|
|
|
|
|
label: `${item.code || item.componentCode || ''} ${item.name || item.componentName || ''}`.trim() || String(item.id),
|
|
|
|
|
raw: item
|
|
|
|
|
}))
|
|
|
|
|
} catch (error) {
|
|
|
|
|
componentOptions.value = []
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function fetchDetail(id) {
|
|
|
|
|
loading.value = true
|
|
|
|
|
try {
|
|
|
|
|
@ -331,6 +419,7 @@ async function fetchDetail(id) {
|
|
|
|
|
formData.repairName = inputValue(detail?.repairName)
|
|
|
|
|
formData.isCode = detail?.isCode === undefined ? true : Boolean(detail?.isCode)
|
|
|
|
|
formData.deviceId = detail?.deviceId ?? detail?.machineryId
|
|
|
|
|
formData.componentId = detail?.componentId ?? detail?.criticalComponentId
|
|
|
|
|
formData.machineryId = detail?.machineryId ?? detail?.deviceId
|
|
|
|
|
formData.machineryCode = inputValue(detail?.machineryCode)
|
|
|
|
|
formData.machineryName = inputValue(detail?.machineryName)
|
|
|
|
|
@ -344,6 +433,7 @@ async function fetchDetail(id) {
|
|
|
|
|
formData.repairResult = normalizedRepairStatus
|
|
|
|
|
formData.acceptedBy = normalizeUserId(detail?.acceptedBy)
|
|
|
|
|
formData.confirmBy = normalizeUserId(detail?.confirmBy)
|
|
|
|
|
formData.faultLevel = detail?.faultLevel === undefined || detail?.faultLevel === null ? '' : String(detail?.faultLevel)
|
|
|
|
|
formData.isShutdown = detail?.isShutdown === undefined || detail?.isShutdown === null ? undefined : Boolean(detail?.isShutdown)
|
|
|
|
|
formData.status = detail?.status === undefined || detail?.status === null ? '0' : String(detail?.status)
|
|
|
|
|
formData.faultPhenomenon = inputValue(detail?.faultPhenomenon)
|
|
|
|
|
@ -373,8 +463,18 @@ async function fetchDetail(id) {
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (formData.componentId !== undefined && formData.componentId !== null) {
|
|
|
|
|
const exists = componentOptions.value.some((item) => String(item.value) === String(formData.componentId))
|
|
|
|
|
if (!exists) {
|
|
|
|
|
componentOptions.value.unshift({
|
|
|
|
|
value: formData.componentId,
|
|
|
|
|
label: `${detail?.componentCode || detail?.criticalComponentCode || ''} ${detail?.componentName || detail?.criticalComponentName || ''}`.trim() || String(formData.componentId),
|
|
|
|
|
raw: detail
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
uni.showToast({ title: '加载详情失败', icon: 'none' })
|
|
|
|
|
uni.showToast({ title: t('equipmentMaintenance.loadDetailFailed'), icon: 'none' })
|
|
|
|
|
} finally {
|
|
|
|
|
loading.value = false
|
|
|
|
|
}
|
|
|
|
|
@ -413,24 +513,42 @@ function onDeviceChange(event) {
|
|
|
|
|
applyDeviceOption(current)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function onComponentChange(event) {
|
|
|
|
|
const index = Number(event?.detail?.value || 0)
|
|
|
|
|
const current = filteredComponentOptions.value[index]
|
|
|
|
|
formData.componentId = current ? current.value : undefined
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function onMachineryTypeChange(event) {
|
|
|
|
|
const nextValue = Number(event?.detail?.value || 1) || 1
|
|
|
|
|
formData.machineryTypeId = nextValue
|
|
|
|
|
formData.deviceId = undefined
|
|
|
|
|
formData.componentId = undefined
|
|
|
|
|
formData.machineryId = undefined
|
|
|
|
|
formData.machineryCode = ''
|
|
|
|
|
formData.machineryName = ''
|
|
|
|
|
formData.machineryBrand = ''
|
|
|
|
|
formData.machinerySpec = ''
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function handleDeviceScan() {
|
|
|
|
|
try {
|
|
|
|
|
const res = await uni.scanCode({ scanType: ['qrCode', 'barCode'] })
|
|
|
|
|
const scan = parseEquipmentScanResult(res?.result)
|
|
|
|
|
if (!scan.id) {
|
|
|
|
|
uni.showToast({ title: '请扫描设备二维码', icon: 'none' })
|
|
|
|
|
uni.showToast({ title: t('equipmentMaintenance.scanEquipmentRequired'), icon: 'none' })
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
const matched = deviceOptions.value.find((item) => String(item.value) === String(scan.id))
|
|
|
|
|
if (!matched) {
|
|
|
|
|
uni.showToast({ title: '未找到对应设备', icon: 'none' })
|
|
|
|
|
uni.showToast({ title: t('equipmentMaintenance.deviceNotFound'), icon: 'none' })
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
applyDeviceOption(matched)
|
|
|
|
|
} catch (error) {
|
|
|
|
|
const message = String(error?.errMsg || '')
|
|
|
|
|
if (message.includes('cancel')) return
|
|
|
|
|
uni.showToast({ title: '扫码失败', icon: 'none' })
|
|
|
|
|
uni.showToast({ title: t('equipmentMaintenance.scanFailed'), icon: 'none' })
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -459,18 +577,38 @@ function parseEquipmentScanResult(result) {
|
|
|
|
|
function applyDeviceOption(current) {
|
|
|
|
|
formData.deviceId = current.value
|
|
|
|
|
formData.machineryId = current.value
|
|
|
|
|
formData.componentId = undefined
|
|
|
|
|
formData.machineryCode = inputValue(current.raw?.deviceCode)
|
|
|
|
|
formData.machineryName = inputValue(current.raw?.deviceName)
|
|
|
|
|
formData.machineryBrand = inputValue(current.raw?.deviceBrand)
|
|
|
|
|
formData.machinerySpec = inputValue(current.raw?.deviceSpec)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function matchesComponentDevice(component, deviceId) {
|
|
|
|
|
if (!component || !deviceId) return false
|
|
|
|
|
const candidates = [
|
|
|
|
|
component.deviceId,
|
|
|
|
|
component.machineryId,
|
|
|
|
|
component.deviceLedgerId,
|
|
|
|
|
component.deviceLedgerid,
|
|
|
|
|
component.parentDeviceId,
|
|
|
|
|
component.parentMachineryId,
|
|
|
|
|
component.ownerDeviceId,
|
|
|
|
|
component.ownerMachineryId
|
|
|
|
|
]
|
|
|
|
|
return candidates.some((item) => item !== undefined && item !== null && String(item) === String(deviceId))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function onShutdownChange(event) {
|
|
|
|
|
const value = String(event?.detail?.value || '')
|
|
|
|
|
if (value === 'true') formData.isShutdown = true
|
|
|
|
|
if (value === 'false') formData.isShutdown = false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function onFaultLevelChange(event) {
|
|
|
|
|
formData.faultLevel = String(event?.detail?.value || '')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function onRepairStatusChange(event) {
|
|
|
|
|
const value = String(event?.detail?.value || '0')
|
|
|
|
|
formData.repairStatus = value
|
|
|
|
|
@ -552,13 +690,13 @@ async function chooseImages(field) {
|
|
|
|
|
const currentCount = splitImages(formData[field]).length
|
|
|
|
|
const remain = Math.max(0, 9 - currentCount)
|
|
|
|
|
if (!remain) {
|
|
|
|
|
uni.showToast({ title: '最多上传 9 张图片', icon: 'none' })
|
|
|
|
|
uni.showToast({ title: t('equipmentMaintenance.maxUploadCount'), icon: 'none' })
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
const res = await uni.chooseImage({ count: remain, sizeType: ['compressed'] })
|
|
|
|
|
const files = Array.isArray(res?.tempFilePaths) ? res.tempFilePaths : []
|
|
|
|
|
if (!files.length) return
|
|
|
|
|
uni.showLoading({ title: '上传中', mask: true })
|
|
|
|
|
uni.showLoading({ title: t('functionCommon.uploading'), mask: true })
|
|
|
|
|
const uploaded = []
|
|
|
|
|
for (const filePath of files) {
|
|
|
|
|
const uploadRes = await uploadRepairImage(filePath)
|
|
|
|
|
@ -576,7 +714,7 @@ async function chooseImages(field) {
|
|
|
|
|
} catch (error) {
|
|
|
|
|
const message = String(error?.errMsg || '')
|
|
|
|
|
if (!message.includes('cancel')) {
|
|
|
|
|
uni.showToast({ title: '图片上传失败', icon: 'none' })
|
|
|
|
|
uni.showToast({ title: t('functionCommon.uploadImageFailed'), icon: 'none' })
|
|
|
|
|
}
|
|
|
|
|
} finally {
|
|
|
|
|
uni.hideLoading()
|
|
|
|
|
@ -608,7 +746,8 @@ function buildPayload() {
|
|
|
|
|
machineryName: formData.machineryName || undefined,
|
|
|
|
|
machineryBrand: formData.machineryBrand || undefined,
|
|
|
|
|
machinerySpec: formData.machinerySpec || undefined,
|
|
|
|
|
machineryTypeId: 1,
|
|
|
|
|
machineryTypeId: Number(formData.machineryTypeId || 1) || 1,
|
|
|
|
|
componentId: Number(formData.machineryTypeId || 1) === 2 ? formData.componentId : undefined,
|
|
|
|
|
requireDate: toTimestamp(formData.requireDate),
|
|
|
|
|
finishDate: toTimestamp(formData.finishDate),
|
|
|
|
|
confirmDate: toTimestamp(formData.confirmDate),
|
|
|
|
|
@ -616,6 +755,7 @@ function buildPayload() {
|
|
|
|
|
repairResult: normalizeRepairStatus(formData.repairStatus),
|
|
|
|
|
acceptedBy: normalizeUserId(formData.acceptedBy) || undefined,
|
|
|
|
|
confirmBy: normalizeUserId(formData.confirmBy) || undefined,
|
|
|
|
|
faultLevel: formData.faultLevel || undefined,
|
|
|
|
|
isShutdown: formData.isShutdown,
|
|
|
|
|
status: mode.value === 'repair' ? '1' : String(formData.status || '0'),
|
|
|
|
|
faultPhenomenon: formData.faultPhenomenon.trim(),
|
|
|
|
|
@ -633,36 +773,48 @@ function buildPayload() {
|
|
|
|
|
|
|
|
|
|
async function submitForm() {
|
|
|
|
|
if (!formData.isCode && !formData.repairCode.trim()) {
|
|
|
|
|
uni.showToast({ title: '请输入维修单编号', icon: 'none' })
|
|
|
|
|
uni.showToast({ title: t('equipmentMaintenance.validatorRepairCodeRequired'), icon: 'none' })
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if (!formData.repairName.trim()) {
|
|
|
|
|
uni.showToast({ title: '请输入维修单名称', icon: 'none' })
|
|
|
|
|
uni.showToast({ title: t('equipmentMaintenance.validatorRepairNameRequired'), icon: 'none' })
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if (!formData.deviceId) {
|
|
|
|
|
uni.showToast({ title: '请选择设备', icon: 'none' })
|
|
|
|
|
uni.showToast({ title: t('equipmentMaintenance.validatorDeviceRequired'), icon: 'none' })
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if (showComponentSelect.value && !formData.componentId) {
|
|
|
|
|
uni.showToast({ title: t('equipmentMaintenance.validatorComponentRequired'), icon: 'none' })
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if (!formData.requireDate) {
|
|
|
|
|
uni.showToast({ title: '请选择报修日期', icon: 'none' })
|
|
|
|
|
uni.showToast({ title: t('equipmentMaintenance.validatorRequireDateRequired'), icon: 'none' })
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if (!formData.faultLevel) {
|
|
|
|
|
uni.showToast({ title: t('equipmentMaintenance.validatorFaultLevelRequired'), icon: 'none' })
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if (formData.isShutdown === undefined) {
|
|
|
|
|
uni.showToast({ title: t('equipmentMaintenance.validatorIsShutdownRequired'), icon: 'none' })
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if (!formData.faultPhenomenon.trim()) {
|
|
|
|
|
uni.showToast({ title: '请输入故障现象', icon: 'none' })
|
|
|
|
|
uni.showToast({ title: t('equipmentMaintenance.validatorFaultPhenomenonRequired'), icon: 'none' })
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if (mode.value === 'repair') {
|
|
|
|
|
if (String(formData.repairStatus || '0') === '0') {
|
|
|
|
|
uni.showToast({ title: '请选择维修结果', icon: 'none' })
|
|
|
|
|
uni.showToast({ title: t('equipmentMaintenance.validatorRepairStatusRequired'), icon: 'none' })
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if (!formData.finishDate) {
|
|
|
|
|
uni.showToast({ title: '请选择完成日期', icon: 'none' })
|
|
|
|
|
uni.showToast({ title: t('equipmentMaintenance.validatorFinishDateRequired'), icon: 'none' })
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if (!formData.confirmDate) {
|
|
|
|
|
uni.showToast({ title: '请选择验收日期', icon: 'none' })
|
|
|
|
|
uni.showToast({ title: t('equipmentMaintenance.validatorConfirmDateRequired'), icon: 'none' })
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -670,10 +822,10 @@ async function submitForm() {
|
|
|
|
|
const payload = buildPayload()
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
uni.showLoading({ title: '保存中', mask: true })
|
|
|
|
|
uni.showLoading({ title: t('equipmentMaintenance.saving'), mask: true })
|
|
|
|
|
if (mode.value === 'create') {
|
|
|
|
|
await createDvRepair(payload)
|
|
|
|
|
uni.showToast({ title: '新增成功', icon: 'success' })
|
|
|
|
|
uni.showToast({ title: t('functionCommon.createSuccess'), icon: 'success' })
|
|
|
|
|
} else if (mode.value === 'repair') {
|
|
|
|
|
await updateDvRepairStatus({
|
|
|
|
|
id: payload.id,
|
|
|
|
|
@ -682,6 +834,8 @@ async function submitForm() {
|
|
|
|
|
confirmDate: payload.confirmDate,
|
|
|
|
|
repairStatus: payload.repairStatus,
|
|
|
|
|
repairResult: payload.repairResult,
|
|
|
|
|
faultLevel: payload.faultLevel,
|
|
|
|
|
isShutdown: payload.isShutdown,
|
|
|
|
|
faultPhenomenon: payload.faultPhenomenon,
|
|
|
|
|
faultDescription: payload.faultDescription || null,
|
|
|
|
|
faultImages: payload.faultImages,
|
|
|
|
|
@ -694,16 +848,16 @@ async function submitForm() {
|
|
|
|
|
remark: payload.remark || '',
|
|
|
|
|
updateReqVOList: []
|
|
|
|
|
})
|
|
|
|
|
uni.showToast({ title: '提交成功', icon: 'success' })
|
|
|
|
|
uni.showToast({ title: t('equipmentMaintenance.submitSuccess'), icon: 'success' })
|
|
|
|
|
} else {
|
|
|
|
|
await updateDvRepair(payload)
|
|
|
|
|
uni.showToast({ title: '保存成功', icon: 'success' })
|
|
|
|
|
uni.showToast({ title: t('equipmentMaintenance.saveSuccess'), icon: 'success' })
|
|
|
|
|
}
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
goBack()
|
|
|
|
|
}, 300)
|
|
|
|
|
} catch (error) {
|
|
|
|
|
uni.showToast({ title: mode.value === 'repair' ? '提交失败' : '保存失败', icon: 'none' })
|
|
|
|
|
uni.showToast({ title: mode.value === 'repair' ? t('equipmentMaintenance.submitFailed') : t('functionCommon.saveFailed'), icon: 'none' })
|
|
|
|
|
} finally {
|
|
|
|
|
uni.hideLoading()
|
|
|
|
|
}
|
|
|
|
|
|