|
|
<template>
|
|
|
<view class="inventory-bg">
|
|
|
<view class="inventory-card">
|
|
|
<view class="readonly-group">
|
|
|
<view class="readonly-item">
|
|
|
<text class="readonly-label">一级分类</text>
|
|
|
<text class="readonly-value">{{ firstCategory }}</text>
|
|
|
</view>
|
|
|
<view class="readonly-item">
|
|
|
<text class="readonly-label">二级分类</text>
|
|
|
<text class="readonly-value">{{ secondCategory }}</text>
|
|
|
</view>
|
|
|
<view class="readonly-item">
|
|
|
<text class="readonly-label">所属种类</text>
|
|
|
<text class="readonly-value">{{ categoryName }}</text>
|
|
|
</view>
|
|
|
<view class="readonly-item">
|
|
|
<text class="readonly-label">物资名称</text>
|
|
|
<text class="readonly-value">{{ materialName }}</text>
|
|
|
</view>
|
|
|
<!-- <view class="readonly-item">
|
|
|
<text class="readonly-label">物质代码</text>
|
|
|
<text class="readonly-value">{{ materialCode }}</text>
|
|
|
</view> -->
|
|
|
<view class="readonly-item">
|
|
|
<text class="readonly-label">物资类型</text>
|
|
|
<text class="readonly-value">{{ materialType }}</text>
|
|
|
</view>
|
|
|
<view class="readonly-item">
|
|
|
<text class="readonly-label">物资型号</text>
|
|
|
<text class="readonly-value">{{ materialSpec }}</text>
|
|
|
</view>
|
|
|
<view class="readonly-item">
|
|
|
<text class="readonly-label">物资规格</text>
|
|
|
<text class="readonly-value">{{ materialSize }}</text>
|
|
|
</view>
|
|
|
<view class="readonly-item">
|
|
|
<text class="readonly-label">单位</text>
|
|
|
<text class="readonly-value">{{ unit }}</text>
|
|
|
</view>
|
|
|
<view class="readonly-item">
|
|
|
<text class="readonly-label">入库批次</text>
|
|
|
<text class="readonly-value">{{ batchNumber }}</text>
|
|
|
</view>
|
|
|
<view class="readonly-item">
|
|
|
<text class="readonly-label">在库数量</text>
|
|
|
<text class="readonly-value">{{ stockQty }}{{ unit ? ' ' + unit : '' }}</text>
|
|
|
</view>
|
|
|
<view class="readonly-item">
|
|
|
<text class="readonly-label">顺序号</text>
|
|
|
<text class="readonly-value">{{ sequenceNumber }}</text>
|
|
|
</view>
|
|
|
<view class="readonly-item">
|
|
|
<text class="readonly-label">待出库</text>
|
|
|
<text class="readonly-value">{{ waitNum }}</text>
|
|
|
</view>
|
|
|
<view class="readonly-item">
|
|
|
<text class="readonly-label">生产日期</text>
|
|
|
<text class="readonly-value">{{ productionDate }}</text>
|
|
|
</view>
|
|
|
<view class="readonly-item">
|
|
|
<text class="readonly-label">入库日期</text>
|
|
|
<text class="readonly-value">{{ storageDate }}</text>
|
|
|
</view>
|
|
|
<view class="readonly-item">
|
|
|
<text class="readonly-label">物资状态</text>
|
|
|
<text class="readonly-value">{{ materialStatus }}</text>
|
|
|
</view>
|
|
|
<view class="readonly-item">
|
|
|
<text class="readonly-label">储备方式</text>
|
|
|
<text class="readonly-value">{{ reserveMethod }}</text>
|
|
|
</view>
|
|
|
<view class="readonly-item">
|
|
|
<text class="readonly-label">所在仓库</text>
|
|
|
<view class="readonly-value">{{ warehouseName }}</view>
|
|
|
</view>
|
|
|
<view class="readonly-item">
|
|
|
<text class="readonly-label">所在货架</text>
|
|
|
<text class="readonly-value">{{ shelfName }}</text>
|
|
|
</view>
|
|
|
<view class="readonly-item">
|
|
|
<text class="readonly-label">所在货架层</text>
|
|
|
<text class="readonly-value">{{ shelfLayer }}</text>
|
|
|
</view>
|
|
|
<view class="readonly-item">
|
|
|
<text class="readonly-label">等级分类</text>
|
|
|
<text class="readonly-value">{{ levelCategory }}</text>
|
|
|
</view>
|
|
|
<view class="readonly-item">
|
|
|
<text class="readonly-label">产权信息</text>
|
|
|
<text class="readonly-value">{{ propertyInfo }}</text>
|
|
|
</view>
|
|
|
<view class="readonly-item">
|
|
|
<text class="readonly-label">是否为固定资产</text>
|
|
|
<text class="readonly-value">{{ isFixedAsset }}</text>
|
|
|
</view>
|
|
|
<view class="readonly-item">
|
|
|
<text class="readonly-label">固定资产编码</text>
|
|
|
<text class="readonly-value">{{ fixedAssetCode }}</text>
|
|
|
</view>
|
|
|
<view class="readonly-item">
|
|
|
<text class="readonly-label">储备年限</text>
|
|
|
<text class="readonly-value">{{ reserveYears }}</text>
|
|
|
</view>
|
|
|
<view class="readonly-item">
|
|
|
<text class="readonly-label">存放要求</text>
|
|
|
<text class="readonly-value">{{ storageRequirement }}</text>
|
|
|
</view>
|
|
|
<view class="readonly-item">
|
|
|
<text class="readonly-label">维护要求</text>
|
|
|
<text class="readonly-value">{{ maintenanceRequirement }}</text>
|
|
|
</view>
|
|
|
<view class="readonly-item">
|
|
|
<text class="readonly-label">保养频次</text>
|
|
|
<text class="readonly-value">{{ maintenanceFrequency }}</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
<!-- 盘点按钮 -->
|
|
|
<view class="inventory-action-section" v-if="!isViewMode">
|
|
|
<button class="inventory-action-btn" @click="showInventoryModal">盘点</button>
|
|
|
</view>
|
|
|
<!-- 运维记录 -->
|
|
|
<view class="maintenance-section">
|
|
|
<view class="section-title">运维记录</view>
|
|
|
<view class="maintenance-list" v-if="maintenanceRecords.length > 0">
|
|
|
<view class="maintenance-item" v-for="(record, index) in maintenanceRecords" :key="index">
|
|
|
<view class="maintenance-row">
|
|
|
<text class="maintenance-label">记录编号:</text>
|
|
|
<text class="maintenance-value">{{record.no || '-'}}</text>
|
|
|
</view>
|
|
|
<view class="maintenance-row">
|
|
|
<text class="maintenance-label">计划维护日期:</text>
|
|
|
<text class="maintenance-value">{{formatDate(record.planned_maintenance_date) || '-'}}</text>
|
|
|
</view>
|
|
|
<view class="maintenance-row">
|
|
|
<text class="maintenance-label">截止日期:</text>
|
|
|
<text class="maintenance-value">{{formatDate(record.end_date) || '-'}}</text>
|
|
|
</view>
|
|
|
<view class="maintenance-row">
|
|
|
<text class="maintenance-label">负责人:</text>
|
|
|
<text class="maintenance-value">{{record.responsible_admin?record.responsible_admin.name : '-'}}</text>
|
|
|
</view>
|
|
|
<view class="maintenance-row">
|
|
|
<text class="maintenance-label">运维内容:</text>
|
|
|
<text class="maintenance-value">
|
|
|
<span v-if="record.equipment_maintain_config_id && record.equipment_maintain_config && record.equipment_maintain_config.name">
|
|
|
{{ record.equipment_maintain_config.name }}
|
|
|
</span>
|
|
|
<span v-else-if="record.content">
|
|
|
{{ record.content }}
|
|
|
</span>
|
|
|
<span v-else>-</span>
|
|
|
</text>
|
|
|
</view>
|
|
|
<view class="maintenance-row">
|
|
|
<text class="maintenance-label">状态:</text>
|
|
|
<text class="maintenance-value">{{record.status === 1 ? '已完成' : '待处理'}}</text>
|
|
|
</view>
|
|
|
<view class="maintenance-row">
|
|
|
<text class="maintenance-label">实际维护日期/状态:</text>
|
|
|
<view class="maintenance-value">
|
|
|
<text v-if="record.status === 1">{{formatDate(record.maintenance_date) || '-'}}</text>
|
|
|
<view v-else :class="['status-badge', getBadgeClass(record.end_date)]">
|
|
|
{{ getBadgeText(record.end_date) }}
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
<view class="maintenance-actions">
|
|
|
<button v-if="record.status === 0" class="action-btn complete-btn" @click="completeMaintenance(record)">完成维护</button>
|
|
|
<button v-if="record.status === 1" class="action-btn view-btn" @click="viewMaintenance(record)">查看</button>
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
<view class="empty-maintenance" v-else>
|
|
|
<text>暂无运维记录</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
<!-- 盘点弹窗 -->
|
|
|
<view class="inventory-modal" v-if="showModal" @click="closeInventoryModal">
|
|
|
<view class="modal-content" @click.stop>
|
|
|
<view class="modal-header">
|
|
|
<text class="modal-title">物资盘点</text>
|
|
|
<view class="modal-close" @click="closeInventoryModal">
|
|
|
<text class="close-icon">×</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
<view class="modal-body">
|
|
|
<view class="form-group">
|
|
|
<text class="form-label">盘点数量</text>
|
|
|
<input class="form-input" type="number" v-model="countQty" placeholder="请输入盘点数量" />
|
|
|
</view>
|
|
|
<view class="form-group">
|
|
|
<text class="form-label">盘点备注</text>
|
|
|
<textarea class="form-textarea" v-model="remark" placeholder="请输入备注信息" />
|
|
|
</view>
|
|
|
<view class="form-group">
|
|
|
<text class="form-label">照片上传</text>
|
|
|
<view class="photo-upload">
|
|
|
<view v-for="(photo, index) in photos" :key="index" class="photo-preview">
|
|
|
<image :src="photo" mode="aspectFill" class="photo-img" />
|
|
|
<view class="photo-del" @click="deletePhoto(index)">
|
|
|
<text class="delete-icon">×</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
<button v-if="photos.length < 3" class="photo-btn" @click="choosePhoto">
|
|
|
<text class="iconfont icon-camera"></text>
|
|
|
<text class="btn-text">上传照片</text>
|
|
|
</button>
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
<view class="modal-footer">
|
|
|
<button class="modal-btn cancel-btn" @click="closeInventoryModal">取消</button>
|
|
|
<button class="modal-btn submit-btn" @click="submit">提交盘点</button>
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
<!-- 运维记录详情弹窗 -->
|
|
|
<view class="detail-modal" v-if="showDetailModal" @click="closeDetailModal">
|
|
|
<view class="detail-modal-content" @click.stop>
|
|
|
<view class="detail-modal-header">
|
|
|
<text class="detail-modal-title">运维记录详情</text>
|
|
|
<view class="detail-modal-close" @click="closeDetailModal">
|
|
|
<text class="close-icon">×</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
<scroll-view class="detail-modal-body" scroll-y>
|
|
|
<view class="detail-form-group">
|
|
|
<text class="detail-form-label">计划维护日期:</text>
|
|
|
<text class="detail-form-value">{{ formatDate(currentRecord.planned_maintenance_date) || '-' }}</text>
|
|
|
</view>
|
|
|
<view class="detail-form-group">
|
|
|
<text class="detail-form-label">实际维护日期:</text>
|
|
|
<text class="detail-form-value">{{ formatDate(currentRecord.maintenance_date) || '-' }}</text>
|
|
|
</view>
|
|
|
<view class="detail-form-group">
|
|
|
<text class="detail-form-label">负责人:</text>
|
|
|
<text class="detail-form-value">{{ currentRecord.responsible_admin?currentRecord.responsible_admin.name : '-' }}</text>
|
|
|
</view>
|
|
|
<view class="detail-form-group">
|
|
|
<text class="detail-form-label">运维内容:</text>
|
|
|
<text class="detail-form-value">{{ currentRecord.content || '-' }}</text>
|
|
|
</view>
|
|
|
<view class="detail-form-group">
|
|
|
<text class="detail-form-label">维护备注:</text>
|
|
|
<text class="detail-form-value">{{ currentRecord.maintenance_content || '-' }}</text>
|
|
|
</view>
|
|
|
<view class="detail-form-group">
|
|
|
<text class="detail-form-label">维护照片:</text>
|
|
|
<view v-if="currentRecord.files && currentRecord.files.length" class="detail-photo-gallery">
|
|
|
<image
|
|
|
v-for="(file, idx) in currentRecord.files"
|
|
|
:key="'file-' + idx"
|
|
|
:src="file.url"
|
|
|
class="detail-photo-preview"
|
|
|
mode="aspectFill"
|
|
|
@click="previewImage(file.url, currentRecord.files.map(f => f.url))"
|
|
|
/>
|
|
|
</view>
|
|
|
<text v-else class="detail-form-value">-</text>
|
|
|
</view>
|
|
|
<view class="detail-form-group">
|
|
|
<text class="detail-form-label">签名照片:</text>
|
|
|
<view v-if="currentRecord.sign && currentRecord.sign.url" class="detail-photo-gallery">
|
|
|
<image
|
|
|
:src="currentRecord.sign.url"
|
|
|
class="detail-sign-preview"
|
|
|
mode="aspectFill"
|
|
|
@click="previewImage(currentRecord.sign.url, [currentRecord.sign.url])"
|
|
|
/>
|
|
|
</view>
|
|
|
<text v-else class="detail-form-value">-</text>
|
|
|
</view>
|
|
|
</scroll-view>
|
|
|
|
|
|
<view class="detail-modal-footer">
|
|
|
<button class="modal-btn submit-btn" @click="closeDetailModal">关闭</button>
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
<!-- 完成维护弹窗 -->
|
|
|
<view class="complete-modal" v-if="showCompleteModal" @click="closeCompleteModal">
|
|
|
<view class="complete-modal-content" @click.stop>
|
|
|
<view class="complete-modal-header">
|
|
|
<text class="complete-modal-title">完成维护</text>
|
|
|
<view class="complete-modal-close" @click="closeCompleteModal">
|
|
|
<text class="close-icon">×</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
<scroll-view class="complete-modal-body" scroll-y>
|
|
|
<view class="complete-form-group">
|
|
|
<text class="complete-form-label">实际维护日期</text>
|
|
|
<picker mode="date" :value="completeForm.actual_date" @change="onDateChange">
|
|
|
<view class="complete-form-input">
|
|
|
<text :class="completeForm.actual_date ? 'input-value' : 'input-placeholder'">
|
|
|
{{ completeForm.actual_date || '请选择实际维护日期' }}
|
|
|
</text>
|
|
|
</view>
|
|
|
</picker>
|
|
|
</view>
|
|
|
|
|
|
<view class="complete-form-group">
|
|
|
<text class="complete-form-label">维护备注</text>
|
|
|
<textarea
|
|
|
class="complete-form-textarea"
|
|
|
v-model="completeForm.notes"
|
|
|
placeholder="请输入维护备注"
|
|
|
:maxlength="500"
|
|
|
/>
|
|
|
</view>
|
|
|
|
|
|
<view class="complete-form-group">
|
|
|
<text class="complete-form-label">上传图片</text>
|
|
|
<view class="complete-photo-upload">
|
|
|
<view v-for="(photo, index) in completeForm.photos" :key="index" class="complete-photo-preview">
|
|
|
<image :src="photo.url" mode="aspectFill" class="complete-photo-img" />
|
|
|
<view class="complete-photo-del" @click="removeCompletePhoto(index)">
|
|
|
<text class="delete-icon">×</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
<button v-if="completeForm.photos.length < 9" class="complete-photo-btn" @click="chooseCompletePhoto">
|
|
|
<text class="iconfont icon-camera"></text>
|
|
|
<text class="btn-text">上传照片</text>
|
|
|
</button>
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
<view class="complete-form-group">
|
|
|
<text class="complete-form-label">签名</text>
|
|
|
<view class="signature-wrapper">
|
|
|
<canvas
|
|
|
canvas-id="signatureCanvas"
|
|
|
class="signature-canvas"
|
|
|
disable-scroll="true"
|
|
|
@touchstart="onTouchStart"
|
|
|
@touchmove="onTouchMove"
|
|
|
@touchend="onTouchEnd"
|
|
|
></canvas>
|
|
|
<view class="signature-actions">
|
|
|
<button class="signature-btn" @click="clearSignature">清除签名</button>
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
</scroll-view>
|
|
|
|
|
|
<view class="complete-modal-footer">
|
|
|
<button class="modal-btn cancel-btn" @click="closeCompleteModal">取消</button>
|
|
|
<button class="modal-btn submit-btn" @click="submitCompleteMaintenance">确认完成</button>
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
import { getMaterialInfo, saveInventoryCheck, uploadFile, getMaintenanceRecord, getMaintenanceRecordDetail, submitMaintenanceRecord } from '@/api.js'
|
|
|
export default {
|
|
|
data() {
|
|
|
return {
|
|
|
isViewMode: false,
|
|
|
stockQty: '',
|
|
|
countQty: '',
|
|
|
remark: '',
|
|
|
photo: '',
|
|
|
photos: [],
|
|
|
material_info_id:'',
|
|
|
// 物资信息
|
|
|
firstCategory: '-',
|
|
|
secondCategory: '-',
|
|
|
categoryName: '-',
|
|
|
materialName: '-',
|
|
|
materialCode: '-',
|
|
|
materialType: '-',
|
|
|
materialSpec: '-',
|
|
|
materialSize: '-',
|
|
|
unit: '-',
|
|
|
// 库存信息
|
|
|
batchNumber: '-',
|
|
|
sequenceNumber: '-',
|
|
|
waitNum: '-',
|
|
|
// 物资明细
|
|
|
productionDate: '-',
|
|
|
storageDate: '-',
|
|
|
materialStatus: '-',
|
|
|
reserveMethod: '-',
|
|
|
warehouseName: '-',
|
|
|
shelfName: '-',
|
|
|
shelfLayer: '-',
|
|
|
levelCategory: '-',
|
|
|
propertyInfo: '-',
|
|
|
isFixedAsset: '-',
|
|
|
fixedAssetCode: '-',
|
|
|
reserveYears: '-',
|
|
|
storageRequirement: '-',
|
|
|
maintenanceRequirement: '-',
|
|
|
maintenanceFrequency: '-',
|
|
|
material_infos_plan_id: '',
|
|
|
materialId: '',
|
|
|
// 运维记录
|
|
|
maintenanceRecords: [],
|
|
|
// 弹窗控制
|
|
|
showModal: false,
|
|
|
// 查看详情
|
|
|
showDetailModal: false,
|
|
|
currentRecord: {},
|
|
|
// 完成维护弹窗
|
|
|
showCompleteModal: false,
|
|
|
completeForm: {
|
|
|
actual_date: '',
|
|
|
notes: '',
|
|
|
photos: [], // [{id: xxx, url: xxx}]
|
|
|
signature: '' // 签名图片路径
|
|
|
},
|
|
|
currentMaintenanceRecord: null, // 当前要完成的维护记录
|
|
|
signatureCtx: null, // 签名画布上下文
|
|
|
signaturePoints: [], // 签名点数组
|
|
|
isDrawing: false // 是否正在绘制签名
|
|
|
}
|
|
|
},
|
|
|
onLoad(options) {
|
|
|
this.isViewMode = options.view === '1';
|
|
|
this.date = this.getToday();
|
|
|
this.materialId = options.code;
|
|
|
console.log("materialId:", this.materialId);
|
|
|
if (this.materialId) {
|
|
|
getMaterialInfo(this.materialId).then(response => {
|
|
|
console.log("response:", response);
|
|
|
if (response.data) {
|
|
|
const data = response.data;
|
|
|
this.material_info_id = data.wuzibianma_material_infos_wuzibianma_relation.id;
|
|
|
const relation = data.wuzibianma_material_infos_wuzibianma_relation || {};
|
|
|
const fenleiDetail = relation.fenlei_detail || {};
|
|
|
const wuzizhuangtaiDetail = data.wuzizhuangtai_detail || {};
|
|
|
const chubeifangshiDetail = data.chubeifangshi_detail || {};
|
|
|
const dengjifenleiDetail = data.dengjifenlei_detail || {};
|
|
|
const chanquanxinxiDetail = data.chanquanxinxi_detail || {};
|
|
|
const materialstorages = data.materialstorages || {};
|
|
|
const shelfs = data.shelfs || {};
|
|
|
const equipmentMaintainConfig = data.equipment_maintain_config || {};
|
|
|
|
|
|
// 物资信息
|
|
|
// 一级分类、二级分类 - 从 material_info_type 分割
|
|
|
const materialInfoType = data.material_info_type || '';
|
|
|
if (materialInfoType) {
|
|
|
const parts = materialInfoType.split('-');
|
|
|
this.firstCategory = parts[0] || '-';
|
|
|
this.secondCategory = parts.length > 1 ? parts[1] : parts[0] || '-';
|
|
|
}
|
|
|
|
|
|
// 所属种类
|
|
|
this.categoryName = fenleiDetail.name || '-';
|
|
|
|
|
|
// 物资名称
|
|
|
this.materialName = data.zichanmingcheng || '-';
|
|
|
|
|
|
// 物质代码
|
|
|
this.materialCode = data.wuzibianma || '-';
|
|
|
|
|
|
// 物资类型
|
|
|
this.materialType = data.wuzileixing || '-';
|
|
|
|
|
|
// 物资型号
|
|
|
this.materialSpec = relation.guigexinghao || data.guigexinghao || '-';
|
|
|
|
|
|
// 物资规格
|
|
|
this.materialSize = relation.wuziguige || '-';
|
|
|
|
|
|
// 单位
|
|
|
this.unit = relation.jiliangdanwei || data.jiliangdanwei || '-';
|
|
|
|
|
|
// 库存信息
|
|
|
// 入库批次
|
|
|
this.batchNumber = data.rukupici || '-';
|
|
|
|
|
|
// 在库数量
|
|
|
this.stockQty = data.zaikushuliang || data.inventorys_total || '0';
|
|
|
|
|
|
// 顺序号
|
|
|
this.sequenceNumber = data.shunxuhao || '-';
|
|
|
|
|
|
// 待出库
|
|
|
this.waitNum = data.wait_num || '-';
|
|
|
|
|
|
// 物资明细
|
|
|
// 生产日期
|
|
|
this.productionDate = data.shengchanriqi || '-';
|
|
|
|
|
|
// 入库日期
|
|
|
this.storageDate = data.rukuriqi || '-';
|
|
|
|
|
|
// 物资状态
|
|
|
this.materialStatus = wuzizhuangtaiDetail.value || '-';
|
|
|
|
|
|
// 储备方式
|
|
|
this.reserveMethod = chubeifangshiDetail.value || '-';
|
|
|
|
|
|
// 所在仓库
|
|
|
this.warehouseName = materialstorages.cangkumingcheng || '-';
|
|
|
|
|
|
// 所在货架
|
|
|
this.shelfName = shelfs.huojiamingcheng || '-';
|
|
|
|
|
|
// 所在货架层
|
|
|
this.shelfLayer = data.huojiaceng || '-';
|
|
|
|
|
|
// 等级分类
|
|
|
this.levelCategory = dengjifenleiDetail.value || '-';
|
|
|
|
|
|
// 产权信息
|
|
|
this.propertyInfo = chanquanxinxiDetail.value || '-';
|
|
|
|
|
|
// 是否为固定资产
|
|
|
this.isFixedAsset = data.shifouweigudingzichan || '-';
|
|
|
|
|
|
// 固定资产编码
|
|
|
this.fixedAssetCode = data.gudingzichanbianma || '-';
|
|
|
|
|
|
// 储备年限
|
|
|
this.reserveYears = data.chubeinianxian || '-';
|
|
|
|
|
|
// 存放要求
|
|
|
this.storageRequirement = data.cunfangyaoqiu || '-';
|
|
|
|
|
|
// 维护要求
|
|
|
this.maintenanceRequirement = data.weihuyaoqiu || '-';
|
|
|
|
|
|
// 保养频次
|
|
|
this.maintenanceFrequency = equipmentMaintainConfig.name || '-';
|
|
|
|
|
|
// material_infos_plan_id
|
|
|
this.material_infos_plan_id = data.material_infos_plan_id || '';
|
|
|
} else {
|
|
|
uni.showToast({ title: '未获取到物资信息', icon: 'none' })
|
|
|
}
|
|
|
}).catch(() => {
|
|
|
uni.showToast({ title: '获取物资信息失败', icon: 'none' })
|
|
|
})
|
|
|
|
|
|
// 获取运维记录
|
|
|
this.getMaintenanceRecords()
|
|
|
}
|
|
|
},
|
|
|
methods: {
|
|
|
// 显示盘点弹窗
|
|
|
showInventoryModal() {
|
|
|
this.showModal = true;
|
|
|
},
|
|
|
// 关闭盘点弹窗
|
|
|
closeInventoryModal() {
|
|
|
this.showModal = false;
|
|
|
},
|
|
|
getToday() {
|
|
|
const now = new Date();
|
|
|
const y = now.getFullYear();
|
|
|
const m = String(now.getMonth() + 1).padStart(2, '0');
|
|
|
const d = String(now.getDate()).padStart(2, '0');
|
|
|
return `${y}-${m}-${d}`;
|
|
|
},
|
|
|
choosePhoto() {
|
|
|
if (this.photos.length >= 3) {
|
|
|
uni.showToast({ title: '最多上传3张照片', icon: 'none' });
|
|
|
return;
|
|
|
}
|
|
|
uni.chooseImage({
|
|
|
count: 3 - this.photos.length,
|
|
|
success: (res) => {
|
|
|
this.photos = [...this.photos, ...res.tempFilePaths];
|
|
|
}
|
|
|
});
|
|
|
},
|
|
|
deletePhoto(index) {
|
|
|
this.photos.splice(index, 1);
|
|
|
},
|
|
|
async submit() {
|
|
|
if (!this.countQty) {
|
|
|
uni.showToast({ title: '请输入盘点数量', icon: 'none' });
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if (!/^(0|[1-9][0-9]*)$/.test(this.countQty)) {
|
|
|
uni.showToast({ title: '盘点数量必须为0或正整数', icon: 'none' });
|
|
|
return;
|
|
|
}
|
|
|
uni.showLoading({ title: '提交中...' });
|
|
|
// 1. 上传所有照片,收集 file_id
|
|
|
let file_ids = [];
|
|
|
for (let i = 0; i < this.photos.length; i++) {
|
|
|
try {
|
|
|
const res = await uploadFile(this.photos[i]);
|
|
|
if (res && res.id) {
|
|
|
file_ids.push(res.id);
|
|
|
}
|
|
|
} catch (e) {
|
|
|
uni.hideLoading();
|
|
|
uni.showToast({ title: '图片上传失败', icon: 'none' });
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
// 2. 组装盘点数据
|
|
|
const data = {
|
|
|
status: '1',
|
|
|
inventorys_id:this.materialId,
|
|
|
check_num: this.countQty,
|
|
|
remark: this.remark,
|
|
|
file_ids
|
|
|
// 其他参数如 material_infos_plan_id、status、check_date 可按需补充
|
|
|
};
|
|
|
console.log("data:", data);
|
|
|
// 3. 提交盘点
|
|
|
saveInventoryCheck(data).then(res => {
|
|
|
console.log("res:", res);
|
|
|
uni.hideLoading();
|
|
|
if (res && (!res.data || res.data.errcode === undefined)) {
|
|
|
uni.showToast({ title: '盘点提交成功', icon: 'success' });
|
|
|
setTimeout(() => {
|
|
|
uni.reLaunch({ url: '/pages/index/index' });
|
|
|
}, 1200);
|
|
|
} else {
|
|
|
uni.showToast({ title: res.data.errmsg || '提交失败', icon: 'none' });
|
|
|
}
|
|
|
}).catch(() => {
|
|
|
uni.hideLoading();
|
|
|
uni.showToast({ title: '提交失败', icon: 'none' });
|
|
|
});
|
|
|
},
|
|
|
// 获取运维记录
|
|
|
async getMaintenanceRecords() {
|
|
|
if (!this.materialId) return;
|
|
|
|
|
|
try {
|
|
|
const params = {
|
|
|
page: 1,
|
|
|
page_size: 999,
|
|
|
'filter[0][key]': 'inventorys_id',
|
|
|
'filter[0][op]': 'eq',
|
|
|
'filter[0][value]': this.materialId
|
|
|
};
|
|
|
|
|
|
const res = await getMaintenanceRecord(params);
|
|
|
console.log("运维记录响应:", res);
|
|
|
|
|
|
if (res.data && res.data.list && res.data.list.data) {
|
|
|
this.maintenanceRecords = res.data.list.data;
|
|
|
} else {
|
|
|
this.maintenanceRecords = [];
|
|
|
}
|
|
|
} catch (error) {
|
|
|
console.error('获取运维记录失败:', error);
|
|
|
this.maintenanceRecords = [];
|
|
|
}
|
|
|
},
|
|
|
// 格式化日期
|
|
|
formatDate(dateStr) {
|
|
|
if (!dateStr) return '-';
|
|
|
// 如果已经是 YYYY-MM-DD 格式,直接返回
|
|
|
if (/^\d{4}-\d{2}-\d{2}$/.test(dateStr)) {
|
|
|
return dateStr;
|
|
|
}
|
|
|
const date = new Date(dateStr);
|
|
|
if (isNaN(date.getTime())) {
|
|
|
return dateStr; // 如果无法解析,返回原值
|
|
|
}
|
|
|
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}`;
|
|
|
},
|
|
|
// 获取日期差值(天数)
|
|
|
getDateDifferenceInDays(dateString) {
|
|
|
if (!dateString) return 0;
|
|
|
const plannedDate = new Date(dateString);
|
|
|
const today = new Date();
|
|
|
|
|
|
// 设置时间为当天的 00:00:00
|
|
|
today.setHours(0, 0, 0, 0);
|
|
|
plannedDate.setHours(0, 0, 0, 0);
|
|
|
|
|
|
// 计算日期差值(毫秒)
|
|
|
const diffTime = plannedDate - today;
|
|
|
|
|
|
// 转换为天数
|
|
|
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
|
|
|
|
|
|
return diffDays;
|
|
|
},
|
|
|
// 获取状态徽章文本
|
|
|
getBadgeText(endDate) {
|
|
|
if (!endDate) {
|
|
|
return '-';
|
|
|
}
|
|
|
const diffDays = this.getDateDifferenceInDays(endDate);
|
|
|
return diffDays >= 0 ? `还有 ${diffDays} 天` : `已超期 ${Math.abs(diffDays)} 天`;
|
|
|
},
|
|
|
// 获取状态徽章样式类
|
|
|
getBadgeClass(endDate) {
|
|
|
if (!endDate) {
|
|
|
return 'status-default';
|
|
|
}
|
|
|
const diffDays = this.getDateDifferenceInDays(endDate);
|
|
|
if (diffDays < 0) {
|
|
|
return 'status-overdue'; // 已超期
|
|
|
} else if (diffDays <= 3) {
|
|
|
return 'status-urgent'; // 紧急(3天内)
|
|
|
} else {
|
|
|
return 'status-normal'; // 正常
|
|
|
}
|
|
|
},
|
|
|
// 完成维护
|
|
|
completeMaintenance(record) {
|
|
|
console.log('完成维护:', record);
|
|
|
this.currentMaintenanceRecord = record;
|
|
|
// 重置表单
|
|
|
this.completeForm = {
|
|
|
actual_date: this.getToday(),
|
|
|
notes: '',
|
|
|
photos: [],
|
|
|
signature: ''
|
|
|
};
|
|
|
this.showCompleteModal = true;
|
|
|
// 初始化签名画布
|
|
|
this.$nextTick(() => {
|
|
|
this.initSignatureCanvas();
|
|
|
});
|
|
|
},
|
|
|
// 关闭完成维护弹窗
|
|
|
closeCompleteModal() {
|
|
|
this.showCompleteModal = false;
|
|
|
this.currentMaintenanceRecord = null;
|
|
|
this.completeForm = {
|
|
|
actual_date: '',
|
|
|
notes: '',
|
|
|
photos: [],
|
|
|
signature: ''
|
|
|
};
|
|
|
},
|
|
|
// 日期选择
|
|
|
onDateChange(e) {
|
|
|
this.completeForm.actual_date = e.detail.value;
|
|
|
},
|
|
|
// 选择完成维护的图片
|
|
|
chooseCompletePhoto() {
|
|
|
if (this.completeForm.photos.length >= 9) {
|
|
|
uni.showToast({ title: '最多上传9张照片', icon: 'none' });
|
|
|
return;
|
|
|
}
|
|
|
uni.chooseImage({
|
|
|
count: 9 - this.completeForm.photos.length,
|
|
|
success: async (res) => {
|
|
|
uni.showLoading({ title: '上传中...' });
|
|
|
try {
|
|
|
for (let i = 0; i < res.tempFilePaths.length; i++) {
|
|
|
const uploadRes = await uploadFile(res.tempFilePaths[i]);
|
|
|
if (uploadRes && uploadRes.id) {
|
|
|
this.completeForm.photos.push({
|
|
|
id: uploadRes.id,
|
|
|
url: uploadRes.url || res.tempFilePaths[i]
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
uni.hideLoading();
|
|
|
} catch (error) {
|
|
|
uni.hideLoading();
|
|
|
uni.showToast({ title: '图片上传失败', icon: 'none' });
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
},
|
|
|
// 删除完成维护的图片
|
|
|
removeCompletePhoto(index) {
|
|
|
this.completeForm.photos.splice(index, 1);
|
|
|
},
|
|
|
// 初始化签名画布
|
|
|
initSignatureCanvas() {
|
|
|
this.$nextTick(() => {
|
|
|
const ctx = uni.createCanvasContext('signatureCanvas', this);
|
|
|
ctx.setStrokeStyle('#000000');
|
|
|
ctx.setLineWidth(3);
|
|
|
ctx.setLineCap('round');
|
|
|
ctx.setLineJoin('round');
|
|
|
this.signatureCtx = ctx;
|
|
|
this.signaturePoints = [];
|
|
|
this.isDrawing = false;
|
|
|
});
|
|
|
},
|
|
|
// 触摸开始
|
|
|
onTouchStart(e) {
|
|
|
if (!this.signatureCtx) {
|
|
|
this.initSignatureCanvas();
|
|
|
return;
|
|
|
}
|
|
|
this.isDrawing = true;
|
|
|
const touch = e.touches[0];
|
|
|
const point = {
|
|
|
x: touch.x,
|
|
|
y: touch.y
|
|
|
};
|
|
|
this.signaturePoints = [point];
|
|
|
this.signatureCtx.beginPath();
|
|
|
this.signatureCtx.moveTo(point.x, point.y);
|
|
|
},
|
|
|
// 触摸移动
|
|
|
onTouchMove(e) {
|
|
|
if (!this.isDrawing || !this.signatureCtx) return;
|
|
|
e.preventDefault();
|
|
|
const touch = e.touches[0];
|
|
|
const point = {
|
|
|
x: touch.x,
|
|
|
y: touch.y
|
|
|
};
|
|
|
if (this.signaturePoints.length > 0) {
|
|
|
const prevPoint = this.signaturePoints[this.signaturePoints.length - 1];
|
|
|
this.signatureCtx.moveTo(prevPoint.x, prevPoint.y);
|
|
|
this.signatureCtx.lineTo(point.x, point.y);
|
|
|
this.signatureCtx.stroke();
|
|
|
this.signatureCtx.draw(true);
|
|
|
}
|
|
|
this.signaturePoints.push(point);
|
|
|
},
|
|
|
// 触摸结束
|
|
|
onTouchEnd() {
|
|
|
this.isDrawing = false;
|
|
|
// 保存签名图片
|
|
|
this.saveSignature();
|
|
|
},
|
|
|
// 保存签名
|
|
|
saveSignature() {
|
|
|
if (!this.signatureCtx) return;
|
|
|
uni.canvasToTempFilePath({
|
|
|
canvasId: 'signatureCanvas',
|
|
|
success: (res) => {
|
|
|
this.completeForm.signature = res.tempFilePath;
|
|
|
},
|
|
|
fail: (err) => {
|
|
|
console.error('保存签名失败:', err);
|
|
|
}
|
|
|
}, this);
|
|
|
},
|
|
|
// 清除签名
|
|
|
clearSignature() {
|
|
|
if (this.signatureCtx) {
|
|
|
// 清除整个画布(使用足够大的值)
|
|
|
this.signatureCtx.clearRect(0, 0, 1000, 1000);
|
|
|
this.signatureCtx.draw(true);
|
|
|
this.completeForm.signature = '';
|
|
|
this.signaturePoints = [];
|
|
|
this.isDrawing = false;
|
|
|
}
|
|
|
},
|
|
|
// 提交完成维护
|
|
|
async submitCompleteMaintenance() {
|
|
|
if (!this.completeForm.actual_date) {
|
|
|
uni.showToast({ title: '请选择实际维护日期', icon: 'none' });
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if (!this.currentMaintenanceRecord || !this.currentMaintenanceRecord.id) {
|
|
|
uni.showToast({ title: '维护记录信息错误', icon: 'none' });
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
uni.showLoading({ title: '提交中...' });
|
|
|
|
|
|
try {
|
|
|
// 上传签名图片
|
|
|
let sign_id = null;
|
|
|
if (this.completeForm.signature) {
|
|
|
const signRes = await uploadFile(this.completeForm.signature);
|
|
|
if (signRes && signRes.id) {
|
|
|
sign_id = signRes.id;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 组装提交数据
|
|
|
const data = {
|
|
|
id: this.currentMaintenanceRecord.id,
|
|
|
maintenance_date: this.formatDate(this.completeForm.actual_date),
|
|
|
maintenance_content: this.completeForm.notes,
|
|
|
file_ids: this.completeForm.photos.map(photo => photo.id),
|
|
|
sign_id: sign_id,
|
|
|
status: 1
|
|
|
};
|
|
|
|
|
|
console.log('提交完成维护数据:', data);
|
|
|
// return
|
|
|
const res = await submitMaintenanceRecord(data);
|
|
|
console.log('提交完成维护响应:', res);
|
|
|
|
|
|
uni.hideLoading();
|
|
|
|
|
|
if (res && (!res.data || res.data.errcode === undefined)) {
|
|
|
uni.showToast({ title: '完成维护成功', icon: 'success' });
|
|
|
this.closeCompleteModal();
|
|
|
// 刷新运维记录列表
|
|
|
this.getMaintenanceRecords();
|
|
|
} else {
|
|
|
uni.showToast({ title: res.data?.errmsg || '提交失败', icon: 'none' });
|
|
|
}
|
|
|
} catch (error) {
|
|
|
console.error('提交完成维护失败:', error);
|
|
|
uni.hideLoading();
|
|
|
uni.showToast({ title: '提交失败', icon: 'none' });
|
|
|
}
|
|
|
},
|
|
|
// 查看维护记录
|
|
|
async viewMaintenance(record) {
|
|
|
console.log('查看维护记录:', record);
|
|
|
if (!record.id) {
|
|
|
uni.showToast({
|
|
|
title: '记录ID不存在',
|
|
|
icon: 'none'
|
|
|
});
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
uni.showLoading({ title: '加载中...' });
|
|
|
try {
|
|
|
const res = await getMaintenanceRecordDetail(record.id);
|
|
|
console.log('运维记录详情:', res);
|
|
|
|
|
|
if (res.data) {
|
|
|
this.currentRecord = res.data;
|
|
|
this.showDetailModal = true;
|
|
|
} else {
|
|
|
uni.showToast({
|
|
|
title: '获取详情失败',
|
|
|
icon: 'none'
|
|
|
});
|
|
|
}
|
|
|
} catch (error) {
|
|
|
console.error('获取运维记录详情失败:', error);
|
|
|
uni.showToast({
|
|
|
title: '获取详情失败',
|
|
|
icon: 'none'
|
|
|
});
|
|
|
} finally {
|
|
|
uni.hideLoading();
|
|
|
}
|
|
|
},
|
|
|
// 关闭详情弹窗
|
|
|
closeDetailModal() {
|
|
|
this.showDetailModal = false;
|
|
|
this.currentRecord = {};
|
|
|
},
|
|
|
// 预览图片
|
|
|
previewImage(currentUrl, urls) {
|
|
|
if (!urls || urls.length === 0) {
|
|
|
urls = [currentUrl];
|
|
|
}
|
|
|
uni.previewImage({
|
|
|
current: currentUrl,
|
|
|
urls: urls
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
<style>
|
|
|
.inventory-bg {
|
|
|
min-height: 100vh;
|
|
|
background: #f5f6f7;
|
|
|
padding: 24rpx;
|
|
|
}
|
|
|
|
|
|
.inventory-card {
|
|
|
background: #fff;
|
|
|
border-radius: 24rpx;
|
|
|
padding: 32rpx 24rpx;
|
|
|
margin-bottom: 24rpx;
|
|
|
}
|
|
|
|
|
|
.readonly-group {
|
|
|
margin-bottom: 32rpx;
|
|
|
padding: 24rpx;
|
|
|
background: #f8f9fa;
|
|
|
border-radius: 16rpx;
|
|
|
}
|
|
|
|
|
|
.readonly-item {
|
|
|
display: flex;
|
|
|
justify-content: space-between;
|
|
|
margin-bottom: 20rpx;
|
|
|
}
|
|
|
|
|
|
.readonly-item:last-child {
|
|
|
margin-bottom: 0;
|
|
|
}
|
|
|
|
|
|
.readonly-label {
|
|
|
color: #666;
|
|
|
font-size: 28rpx;
|
|
|
width:20%;
|
|
|
}
|
|
|
|
|
|
.readonly-value {
|
|
|
color: #333;
|
|
|
font-size: 28rpx;
|
|
|
font-weight: 500;
|
|
|
text-align: right;
|
|
|
width:75%;
|
|
|
}
|
|
|
|
|
|
.form-group {
|
|
|
margin-bottom: 32rpx;
|
|
|
}
|
|
|
|
|
|
.form-label {
|
|
|
font-size: 28rpx;
|
|
|
color: #333;
|
|
|
margin-bottom: 16rpx;
|
|
|
font-weight: 500;
|
|
|
}
|
|
|
|
|
|
.form-input {
|
|
|
height: 88rpx;
|
|
|
background: #f8f9fa;
|
|
|
border: none;
|
|
|
border-radius: 16rpx;
|
|
|
padding: 0 24rpx;
|
|
|
font-size: 28rpx;
|
|
|
color: #333;
|
|
|
}
|
|
|
|
|
|
.form-textarea {
|
|
|
min-height: 160rpx;
|
|
|
background: #f8f9fa;
|
|
|
border: none;
|
|
|
border-radius: 16rpx;
|
|
|
padding: 20rpx 24rpx;
|
|
|
font-size: 28rpx;
|
|
|
color: #333;
|
|
|
}
|
|
|
|
|
|
.photo-upload {
|
|
|
display: flex;
|
|
|
flex-wrap: wrap;
|
|
|
gap: 20rpx;
|
|
|
}
|
|
|
|
|
|
.photo-preview {
|
|
|
position: relative;
|
|
|
width: 160rpx;
|
|
|
height: 160rpx;
|
|
|
}
|
|
|
|
|
|
.photo-btn {
|
|
|
width: 160rpx;
|
|
|
height: 160rpx;
|
|
|
background: #f8f9fa;
|
|
|
border-radius: 16rpx;
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
|
padding: 0;
|
|
|
}
|
|
|
|
|
|
.photo-btn .iconfont {
|
|
|
font-size: 48rpx;
|
|
|
color: #666;
|
|
|
margin-bottom: 8rpx;
|
|
|
}
|
|
|
|
|
|
.btn-text {
|
|
|
font-size: 24rpx;
|
|
|
color: #666;
|
|
|
}
|
|
|
|
|
|
.photo-preview {
|
|
|
position: relative;
|
|
|
}
|
|
|
|
|
|
.photo-img {
|
|
|
width: 160rpx;
|
|
|
height: 160rpx;
|
|
|
border-radius: 16rpx;
|
|
|
}
|
|
|
|
|
|
.photo-del {
|
|
|
position: absolute;
|
|
|
top: -16rpx;
|
|
|
right: -16rpx;
|
|
|
width: 40rpx;
|
|
|
height: 40rpx;
|
|
|
background: rgba(0,0,0,0.6);
|
|
|
border-radius: 50%;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
|
}
|
|
|
|
|
|
.delete-icon {
|
|
|
color: #ff4d4f;
|
|
|
font-size: 32rpx;
|
|
|
font-weight: bold;
|
|
|
line-height: 1;
|
|
|
}
|
|
|
|
|
|
.submit-btn {
|
|
|
width: 100%;
|
|
|
height: 88rpx;
|
|
|
background: #409eff;
|
|
|
color: #fff;
|
|
|
font-size: 32rpx;
|
|
|
font-weight: 500;
|
|
|
border-radius: 44rpx;
|
|
|
margin-top: 48rpx;
|
|
|
}
|
|
|
|
|
|
.submit-btn:active {
|
|
|
opacity: 0.9;
|
|
|
}
|
|
|
|
|
|
/* 运维记录样式 */
|
|
|
.maintenance-section {
|
|
|
margin-bottom: 32rpx;
|
|
|
padding: 24rpx;
|
|
|
background: #f8f9fa;
|
|
|
border-radius: 16rpx;
|
|
|
}
|
|
|
|
|
|
.section-title {
|
|
|
font-size: 32rpx;
|
|
|
font-weight: 700;
|
|
|
color: #333;
|
|
|
margin-bottom: 24rpx;
|
|
|
}
|
|
|
|
|
|
.maintenance-list {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
gap: 24rpx;
|
|
|
}
|
|
|
|
|
|
.maintenance-item {
|
|
|
background: #fff;
|
|
|
border-radius: 16rpx;
|
|
|
padding: 24rpx;
|
|
|
border: 1px solid #e0e0e0;
|
|
|
}
|
|
|
|
|
|
.maintenance-row {
|
|
|
display: flex;
|
|
|
align-items: flex-start;
|
|
|
margin-bottom: 16rpx;
|
|
|
line-height: 1.6;
|
|
|
}
|
|
|
|
|
|
.maintenance-row:last-child {
|
|
|
margin-bottom: 0;
|
|
|
}
|
|
|
|
|
|
.maintenance-label {
|
|
|
font-size: 26rpx;
|
|
|
color: #666;
|
|
|
width: 240rpx;
|
|
|
flex-shrink: 0;
|
|
|
}
|
|
|
|
|
|
.maintenance-value {
|
|
|
font-size: 26rpx;
|
|
|
color: #333;
|
|
|
flex: 1;
|
|
|
word-break: break-all;
|
|
|
}
|
|
|
|
|
|
.maintenance-actions {
|
|
|
margin-top: 20rpx;
|
|
|
padding-top: 20rpx;
|
|
|
border-top: 1px solid #e0e0e0;
|
|
|
display: flex;
|
|
|
justify-content: flex-end;
|
|
|
}
|
|
|
|
|
|
.action-btn {
|
|
|
padding: 12rpx 24rpx;
|
|
|
border-radius: 16rpx;
|
|
|
font-size: 24rpx;
|
|
|
font-weight: 500;
|
|
|
border: none;
|
|
|
margin-left: 16rpx;
|
|
|
}
|
|
|
|
|
|
.complete-btn {
|
|
|
background: linear-gradient(135deg, #52c41a, #73d13d);
|
|
|
color: #fff;
|
|
|
box-shadow: 0 2px 8px rgba(82,196,26,0.3);
|
|
|
}
|
|
|
|
|
|
.complete-btn:active {
|
|
|
opacity: 0.9;
|
|
|
transform: scale(0.98);
|
|
|
}
|
|
|
|
|
|
.view-btn {
|
|
|
background: linear-gradient(135deg, #409eff, #66b1ff);
|
|
|
color: #fff;
|
|
|
box-shadow: 0 2px 8px rgba(64,158,255,0.3);
|
|
|
}
|
|
|
|
|
|
.view-btn:active {
|
|
|
opacity: 0.9;
|
|
|
transform: scale(0.98);
|
|
|
}
|
|
|
|
|
|
.status-badge {
|
|
|
display: inline-block;
|
|
|
padding: 6rpx 12rpx;
|
|
|
border-radius: 12rpx;
|
|
|
font-size: 22rpx;
|
|
|
font-weight: 500;
|
|
|
white-space: nowrap;
|
|
|
}
|
|
|
|
|
|
.status-badge.status-normal {
|
|
|
background: #e6f7ff;
|
|
|
color: #1890ff;
|
|
|
border: 1px solid #91d5ff;
|
|
|
}
|
|
|
|
|
|
.status-badge.status-urgent {
|
|
|
background: #fff7e6;
|
|
|
color: #fa8c16;
|
|
|
border: 1px solid #ffd591;
|
|
|
}
|
|
|
|
|
|
.status-badge.status-overdue {
|
|
|
background: #fff1f0;
|
|
|
color: #ff4d4f;
|
|
|
border: 1px solid #ffccc7;
|
|
|
}
|
|
|
|
|
|
.status-badge.status-default {
|
|
|
background: #f5f5f5;
|
|
|
color: #999;
|
|
|
border: 1px solid #d9d9d9;
|
|
|
}
|
|
|
|
|
|
.empty-maintenance {
|
|
|
text-align: center;
|
|
|
padding: 60rpx 0;
|
|
|
color: #999;
|
|
|
font-size: 28rpx;
|
|
|
}
|
|
|
|
|
|
/* 盘点按钮区域 */
|
|
|
.inventory-action-section {
|
|
|
margin-top: 32rpx;
|
|
|
margin-bottom: 32rpx;
|
|
|
display: flex;
|
|
|
justify-content: center;
|
|
|
}
|
|
|
|
|
|
.inventory-action-btn {
|
|
|
width: 200rpx;
|
|
|
height: 80rpx;
|
|
|
background: linear-gradient(135deg, #409eff, #66b1ff);
|
|
|
color: #fff;
|
|
|
border: none;
|
|
|
border-radius: 40rpx;
|
|
|
font-size: 32rpx;
|
|
|
font-weight: 600;
|
|
|
box-shadow: 0 4px 12px rgba(64,158,255,0.3);
|
|
|
transition: all 0.3s ease;
|
|
|
}
|
|
|
|
|
|
.inventory-action-btn:active {
|
|
|
transform: scale(0.95);
|
|
|
box-shadow: 0 2px 8px rgba(64,158,255,0.4);
|
|
|
}
|
|
|
|
|
|
/* 盘点弹窗样式 */
|
|
|
.inventory-modal {
|
|
|
position: fixed;
|
|
|
top: 0;
|
|
|
left: 0;
|
|
|
right: 0;
|
|
|
bottom: 0;
|
|
|
background: rgba(0, 0, 0, 0.5);
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
|
z-index: 9999;
|
|
|
padding: 40rpx;
|
|
|
box-sizing: border-box;
|
|
|
}
|
|
|
|
|
|
.modal-content {
|
|
|
background: #fff;
|
|
|
border-radius: 24rpx;
|
|
|
width: 100%;
|
|
|
/* max-width: 600rpx; */
|
|
|
max-height: 90vh;
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
overflow: hidden;
|
|
|
}
|
|
|
|
|
|
.modal-header {
|
|
|
display: flex;
|
|
|
justify-content: space-between;
|
|
|
align-items: center;
|
|
|
padding: 32rpx 24rpx;
|
|
|
border-bottom: 1px solid #e0e0e0;
|
|
|
}
|
|
|
|
|
|
.modal-title {
|
|
|
font-size: 36rpx;
|
|
|
font-weight: 700;
|
|
|
color: #333;
|
|
|
}
|
|
|
|
|
|
.modal-close {
|
|
|
width: 60rpx;
|
|
|
height: 60rpx;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
|
border-radius: 50%;
|
|
|
background: #f5f5f5;
|
|
|
cursor: pointer;
|
|
|
}
|
|
|
|
|
|
.modal-close:active {
|
|
|
background: #e0e0e0;
|
|
|
}
|
|
|
|
|
|
.close-icon {
|
|
|
font-size: 48rpx;
|
|
|
color: #666;
|
|
|
line-height: 1;
|
|
|
}
|
|
|
|
|
|
.modal-body {
|
|
|
flex: 1;
|
|
|
padding: 32rpx 24rpx;
|
|
|
overflow-y: auto;
|
|
|
}
|
|
|
|
|
|
.modal-footer {
|
|
|
display: flex;
|
|
|
gap: 24rpx;
|
|
|
padding: 24rpx;
|
|
|
border-top: 1px solid #e0e0e0;
|
|
|
align-items: center;
|
|
|
}
|
|
|
|
|
|
.modal-btn {
|
|
|
flex: 1;
|
|
|
height: 88rpx;
|
|
|
border-radius: 44rpx;
|
|
|
font-size: 32rpx;
|
|
|
font-weight: 500;
|
|
|
border: none;
|
|
|
transition: all 0.3s ease;
|
|
|
margin-top:0;
|
|
|
}
|
|
|
|
|
|
.cancel-btn {
|
|
|
background: #f5f5f5;
|
|
|
color: #666;
|
|
|
}
|
|
|
|
|
|
.cancel-btn:active {
|
|
|
background: #e0e0e0;
|
|
|
transform: scale(0.98);
|
|
|
}
|
|
|
|
|
|
.modal-footer .submit-btn {
|
|
|
background: linear-gradient(135deg, #409eff, #66b1ff);
|
|
|
color: #fff;
|
|
|
box-shadow: 0 4px 12px rgba(64,158,255,0.3);
|
|
|
}
|
|
|
|
|
|
.modal-footer .submit-btn:active {
|
|
|
opacity: 0.9;
|
|
|
transform: scale(0.98);
|
|
|
}
|
|
|
|
|
|
/* 运维记录详情弹窗样式 */
|
|
|
.detail-modal {
|
|
|
position: fixed;
|
|
|
top: 0;
|
|
|
left: 0;
|
|
|
right: 0;
|
|
|
bottom: 0;
|
|
|
background: rgba(0, 0, 0, 0.5);
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
|
z-index: 999;
|
|
|
padding: 40rpx;
|
|
|
box-sizing: border-box;
|
|
|
}
|
|
|
|
|
|
.detail-modal-content {
|
|
|
background: #fff;
|
|
|
border-radius: 24rpx;
|
|
|
width: 100%;
|
|
|
max-width: 700rpx;
|
|
|
max-height: 90vh;
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
overflow: hidden;
|
|
|
}
|
|
|
|
|
|
.detail-modal-header {
|
|
|
display: flex;
|
|
|
justify-content: space-between;
|
|
|
align-items: center;
|
|
|
padding: 32rpx 24rpx;
|
|
|
border-bottom: 1px solid #e0e0e0;
|
|
|
}
|
|
|
|
|
|
.detail-modal-title {
|
|
|
font-size: 36rpx;
|
|
|
font-weight: 700;
|
|
|
color: #333;
|
|
|
}
|
|
|
|
|
|
.detail-modal-close {
|
|
|
width: 60rpx;
|
|
|
height: 60rpx;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
|
border-radius: 50%;
|
|
|
background: #f5f5f5;
|
|
|
cursor: pointer;
|
|
|
}
|
|
|
|
|
|
.detail-modal-close:active {
|
|
|
background: #e0e0e0;
|
|
|
}
|
|
|
|
|
|
.detail-modal-body {
|
|
|
flex: 1;
|
|
|
padding: 32rpx 24rpx;
|
|
|
overflow-y: auto;
|
|
|
}
|
|
|
|
|
|
.detail-form-group {
|
|
|
margin-bottom: 32rpx;
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
gap: 12rpx;
|
|
|
}
|
|
|
|
|
|
.detail-form-group:last-child {
|
|
|
margin-bottom: 0;
|
|
|
}
|
|
|
|
|
|
.detail-form-label {
|
|
|
font-size: 28rpx;
|
|
|
color: #666;
|
|
|
font-weight: 500;
|
|
|
}
|
|
|
|
|
|
.detail-form-value {
|
|
|
font-size: 28rpx;
|
|
|
color: #333;
|
|
|
line-height: 1.6;
|
|
|
word-break: break-all;
|
|
|
}
|
|
|
|
|
|
.detail-photo-gallery {
|
|
|
display: flex;
|
|
|
flex-wrap: wrap;
|
|
|
gap: 20rpx;
|
|
|
margin-top: 12rpx;
|
|
|
}
|
|
|
|
|
|
.detail-photo-preview {
|
|
|
width: 200rpx;
|
|
|
height: 200rpx;
|
|
|
border-radius: 16rpx;
|
|
|
background: #f5f5f5;
|
|
|
}
|
|
|
|
|
|
.detail-sign-preview {
|
|
|
width: 300rpx;
|
|
|
height: 200rpx;
|
|
|
border-radius: 16rpx;
|
|
|
background: #f5f5f5;
|
|
|
}
|
|
|
|
|
|
.detail-modal-footer {
|
|
|
display: flex;
|
|
|
padding: 24rpx;
|
|
|
border-top: 1px solid #e0e0e0;
|
|
|
align-items: center;
|
|
|
}
|
|
|
|
|
|
.detail-modal-footer .submit-btn {
|
|
|
width: 100%;
|
|
|
margin-top: 0;
|
|
|
}
|
|
|
|
|
|
/* 完成维护弹窗样式 */
|
|
|
.complete-modal {
|
|
|
position: fixed;
|
|
|
top: 0;
|
|
|
left: 0;
|
|
|
right: 0;
|
|
|
bottom: 0;
|
|
|
background: rgba(0, 0, 0, 0.5);
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
|
z-index: 998;
|
|
|
padding: 40rpx;
|
|
|
box-sizing: border-box;
|
|
|
}
|
|
|
|
|
|
.complete-modal-content {
|
|
|
background: #fff;
|
|
|
border-radius: 24rpx;
|
|
|
width: 100%;
|
|
|
max-width: 700rpx;
|
|
|
max-height: 90vh;
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
overflow: hidden;
|
|
|
}
|
|
|
|
|
|
.complete-modal-header {
|
|
|
display: flex;
|
|
|
justify-content: space-between;
|
|
|
align-items: center;
|
|
|
padding: 32rpx 24rpx;
|
|
|
border-bottom: 1px solid #e0e0e0;
|
|
|
}
|
|
|
|
|
|
.complete-modal-title {
|
|
|
font-size: 36rpx;
|
|
|
font-weight: 700;
|
|
|
color: #333;
|
|
|
}
|
|
|
|
|
|
.complete-modal-close {
|
|
|
width: 60rpx;
|
|
|
height: 60rpx;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
|
border-radius: 50%;
|
|
|
background: #f5f5f5;
|
|
|
cursor: pointer;
|
|
|
}
|
|
|
|
|
|
.complete-modal-close:active {
|
|
|
background: #e0e0e0;
|
|
|
}
|
|
|
|
|
|
.complete-modal-body {
|
|
|
flex: 1;
|
|
|
padding: 32rpx 24rpx;
|
|
|
overflow-y: auto;
|
|
|
}
|
|
|
|
|
|
.complete-form-group {
|
|
|
margin-bottom: 32rpx;
|
|
|
}
|
|
|
|
|
|
.complete-form-group:last-child {
|
|
|
margin-bottom: 0;
|
|
|
}
|
|
|
|
|
|
.complete-form-label {
|
|
|
font-size: 28rpx;
|
|
|
color: #333;
|
|
|
font-weight: 500;
|
|
|
margin-bottom: 16rpx;
|
|
|
display: block;
|
|
|
}
|
|
|
|
|
|
.complete-form-input {
|
|
|
height: 88rpx;
|
|
|
background: #f8f9fa;
|
|
|
border: none;
|
|
|
border-radius: 16rpx;
|
|
|
padding: 0 24rpx;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
font-size: 28rpx;
|
|
|
}
|
|
|
|
|
|
.input-value {
|
|
|
color: #333;
|
|
|
}
|
|
|
|
|
|
.input-placeholder {
|
|
|
color: #999;
|
|
|
}
|
|
|
|
|
|
.complete-form-textarea {
|
|
|
min-height: 160rpx;
|
|
|
background: #f8f9fa;
|
|
|
border: none;
|
|
|
border-radius: 16rpx;
|
|
|
padding: 20rpx 24rpx;
|
|
|
font-size: 28rpx;
|
|
|
color: #333;
|
|
|
width: 100%;
|
|
|
box-sizing: border-box;
|
|
|
}
|
|
|
|
|
|
.complete-photo-upload {
|
|
|
display: flex;
|
|
|
flex-wrap: wrap;
|
|
|
gap: 20rpx;
|
|
|
}
|
|
|
|
|
|
.complete-photo-preview {
|
|
|
position: relative;
|
|
|
width: 160rpx;
|
|
|
height: 160rpx;
|
|
|
}
|
|
|
|
|
|
.complete-photo-img {
|
|
|
width: 160rpx;
|
|
|
height: 160rpx;
|
|
|
border-radius: 16rpx;
|
|
|
}
|
|
|
|
|
|
.complete-photo-del {
|
|
|
position: absolute;
|
|
|
top: -16rpx;
|
|
|
right: -16rpx;
|
|
|
width: 40rpx;
|
|
|
height: 40rpx;
|
|
|
background: rgba(0,0,0,0.6);
|
|
|
border-radius: 50%;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
|
}
|
|
|
|
|
|
.complete-photo-btn {
|
|
|
width: 160rpx;
|
|
|
height: 160rpx;
|
|
|
background: #f8f9fa;
|
|
|
border-radius: 16rpx;
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
|
padding: 0;
|
|
|
border: none;
|
|
|
}
|
|
|
|
|
|
.complete-photo-btn .iconfont {
|
|
|
font-size: 48rpx;
|
|
|
color: #666;
|
|
|
margin-bottom: 8rpx;
|
|
|
}
|
|
|
|
|
|
/* 签名区域样式 */
|
|
|
.signature-wrapper {
|
|
|
background: #fff;
|
|
|
border: 2px solid #e0e0e0;
|
|
|
border-radius: 16rpx;
|
|
|
padding: 20rpx;
|
|
|
}
|
|
|
|
|
|
.signature-canvas {
|
|
|
width: 100%;
|
|
|
height: 300rpx;
|
|
|
background: #fff;
|
|
|
border: 1px solid #e0e0e0;
|
|
|
border-radius: 8rpx;
|
|
|
touch-action: none;
|
|
|
box-sizing: border-box;
|
|
|
}
|
|
|
|
|
|
.signature-actions {
|
|
|
margin-top: 16rpx;
|
|
|
display: flex;
|
|
|
justify-content: flex-end;
|
|
|
}
|
|
|
|
|
|
.signature-btn {
|
|
|
padding: 12rpx 24rpx;
|
|
|
background: #f5f5f5;
|
|
|
color: #666;
|
|
|
border: none;
|
|
|
border-radius: 16rpx;
|
|
|
font-size: 24rpx;
|
|
|
}
|
|
|
|
|
|
.signature-btn:active {
|
|
|
background: #e0e0e0;
|
|
|
}
|
|
|
|
|
|
.complete-modal-footer {
|
|
|
display: flex;
|
|
|
gap: 24rpx;
|
|
|
padding: 24rpx;
|
|
|
border-top: 1px solid #e0e0e0;
|
|
|
align-items: center;
|
|
|
}
|
|
|
|
|
|
.complete-modal-footer .cancel-btn {
|
|
|
flex: 1;
|
|
|
margin-top: 0;
|
|
|
}
|
|
|
|
|
|
.complete-modal-footer .submit-btn {
|
|
|
flex: 1;
|
|
|
margin-top: 0;
|
|
|
}
|
|
|
</style> |