|
|
<template> <div> <div class="pda-container"> <div class="status-bar"> <div class="goBack" @click="handleBack"><i class="el-icon-arrow-left"></i>上一页</div> <div class="goBack">检验合格入库</div> <div class="network" style="color: #fff" @click="$router.push({ path: '/' })">🏠首页</div> </div>
<!-- 全页面Loading --> <div v-if="loading || scanLoading" class="page-loading-overlay"> <div class="page-loading-content"> <i class="el-icon-loading page-loading-icon"></i> <div class="page-loading-text"> {{ scanLoading ? '验证中...' : loadingText }} </div> </div> </div>
<div style="overflow-y: auto" :class="{ 'content-disabled': loading || scanLoading }"> <!-- Step 1: 扫描采购单号查询接收记录 --> <div v-if="processFlag === 1"> <div class="scan-box" style="margin: 2px;"> <el-input clearable v-model="scanCode" placeholder="扫描或输入采购单号" :editable="false" @keyup.enter.native="searchReceiptList" ref="scanCodeRef" /> </div> <div class="item-list" v-if="receiptList.length > 0" style="margin: 2px;"> <el-form label-position="top" style="margin: 3px;"> <el-row :gutter="5" @click.native="selectReceiptItem(receiptDetail)" v-for="(receiptDetail, index) in receiptList" :key="index" :class="index < receiptList.length - 1 ? 'bottom-line-row' : ''"> <el-col :span="8"> <el-form-item label="物料编码"><span>{{ receiptDetail.sourcePartNo }}</span></el-form-item> </el-col> <el-col :span="8"> <el-form-item label="接收单号"><span>{{ receiptDetail.receiptNo }}</span></el-form-item> </el-col> <el-col :span="8"> <el-form-item label=""> <el-button type="text" class="inboundButton" @click="selectReceiptItem(receiptDetail)" style="margin-top: 10px;margin-left: 20px" size="small">入库</el-button> </el-form-item> </el-col> <el-col :span="24"> <el-form-item label="物料描述"><span>{{ receiptDetail.description }}</span></el-form-item> </el-col> <el-col :span="6"> <el-form-item label="到货数量"><span style="color: #67C23A;">{{ receiptDetail.qtyArrived }}</span></el-form-item> </el-col> <el-col :span="6"> <el-form-item label="供应商"><span>{{ receiptDetail.senderName }}</span></el-form-item> </el-col> <el-col :span="6"> <el-form-item label="PO号"><span>{{ receiptDetail.sourceRef1 }}</span></el-form-item> </el-col> <el-col :span="6"> <el-form-item label="到货日期"><span>{{ formatDate(receiptDetail.arrivalDate) }}</span></el-form-item> </el-col> </el-row> </el-form> </div> </div>
<!-- Step 2: HandlingUnit扫描和入库确认 --> <div v-if="processFlag === 2"> <!-- 接收记录信息显示 --> <div class="material-info-card"> <div class="input-form"> <div class="form-row"> <div class="form-item"> <label class="form-label">物料编码</label> <span > {{ selectedReceipt.sourcePartNo }} </span> </div> <div class="form-item"> <label class="form-label">到货数量</label> <span v-model="selectedReceipt.qtyArrived"> {{selectedReceipt.qtyArrived}} </span> </div> </div> <div class="form-row"> <div class="form-item"> <label class="form-label">物料描述</label> <span v-model="selectedReceipt.description" > {{selectedReceipt.description}} </span> </div> </div> </div> </div>
<!-- 扫描区域 --> <div class="search-container"> <el-input clearable class="compact-input" v-model="scanCode" placeholder="请扫描HandlingUnit条码" prefix-icon="el-icon-search" @keyup.enter.native="handleScan" ref="scanInput" /> <div class="mode-switch"> <el-switch class="custom-switch" v-model="isRemoveMode" active-color="#ff4949" inactive-color="#13ce66"> </el-switch> <span v-if="isRemoveMode" class="switch-text">{{ '移除' }}</span> <span v-else class="switch-text2">{{ '添加' }}</span> </div> </div>
<!-- 目标库位输入 --> <div class="material-info-card"> <div class="input-form"> <div class="form-row"> <div class="form-item"> <el-input v-model="targetLocationId" placeholder="请扫描或输入目标库位" size="small" @keyup.enter.native="handleLocationScan" ref="locationInput"> </el-input> </div> </div> </div> </div>
<!-- 扫描信息确认标题 --> <div class="section-title"> <div class="title-left"> <i class="el-icon-box"></i> <span>扫描信息确认</span> </div> </div>
<!-- 扫描的HandlingUnit明细列表 --> <div class="scanned-items" v-if="scannedItems.length > 0" style="margin: 2px;"> <div class="label-list"> <el-form label-position="top" style="margin: 3px;"> <el-row :gutter="5" v-for="(label, index) in scannedItems" :key="label.id" :class="index < scannedItems.length - 1 ? 'bottom-line-row' : ''" style="border: 1px solid #e0e0e0; border-radius: 4px; margin-bottom: 8px; padding: 8px;"> <el-col :span="16"> <el-form-item label="HandlingUnit"> <span>{{ label.unitId }}</span> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="物料编码"> <span>{{ label.partNo }}</span> </el-form-item> </el-col> <el-col :span="24" v-if="label.partDesc" class="description-col"> <el-form-item label="物料描述"> <span class="part-description">{{ label.partDesc }}</span> </el-form-item> </el-col> <el-col :span="10" v-if="label.batchNo"> <el-form-item label="批次号"> <span>{{ label.batchNo }}</span> </el-form-item> </el-col> <el-col :span="10" v-if="label.locationId"> <el-form-item label="当前库位"> <span>{{ label.locationId }}</span> </el-form-item> </el-col> <el-col :span="4"> <el-form-item label="数量"> <span>{{ label.qty }} </span> </el-form-item> </el-col> </el-row> </el-form> </div> </div>
<!-- 空状态 --> <div v-if="scannedItems.length === 0" class="empty-labels"> <div style="text-align: center; padding: 20px;"> <p style="color: #999; margin: 0;">暂无扫描HandlingUnit</p> </div> </div>
<!-- 底部操作按钮 --> <div class="bottom-actions" v-if="scannedItems.length > 0 || targetLocationId"> <button class="action-btn secondary" @click="processFlag = 1"> 回退 </button> <button class="action-btn primary" @click="confirmStorage"> 确认入库 </button> </div> </div>
<!-- Step 3: 入库历史查询 --> <div v-if="processFlag === 3"> <div class="filter-box" style="margin: 2px;"> <el-button type="text" @click="searchInboundHistory" style="font-size: 16px;">查询入库历史</el-button> </div> <div class="item-list" v-if="historyList.length > 0" style="margin: 2px;"> <el-form label-position="top" style="margin: 3px;"> <el-row :gutter="5" v-for="(historyDetail, index) in historyList" :key="index" :class="index < historyList.length - 1 ? 'bottom-line-row' : ''"> <el-col :span="8"> <el-form-item label="物料编码"><span>{{ historyDetail.partNo }}</span></el-form-item> </el-col> <el-col :span="8"> <el-form-item label="入库单号"><span>{{ historyDetail.transNo }}</span></el-form-item> </el-col> <el-col :span="8"> <el-form-item label="入库状态"> <span style="color: #67C23A;">已入库</span> </el-form-item> </el-col> <el-col :span="24"> <el-form-item label="物料描述"><span>{{ historyDetail.partDesc }}</span></el-form-item> </el-col> <el-col :span="6"> <el-form-item label="入库数量"><span>{{ historyDetail.inboundQty }}</span></el-form-item> </el-col> <el-col :span="6"> <el-form-item label="批次号"><span>{{ historyDetail.batchNo }}</span></el-form-item> </el-col> <el-col :span="6"> <el-form-item label="操作员"><span>{{ historyDetail.operatorName }}</span></el-form-item> </el-col> <el-col :span="6"> <el-form-item label="入库日期"><span>{{ formatDate(historyDetail.inboundDate) }}</span></el-form-item> </el-col> </el-row> </el-form> </div> </div> </div>
<!-- 底部导航 --><!-- <div class="bottom-nav"> <el-button :type="processFlag === 1 ? 'primary' : 'text'" @click="processFlag = 1">待入库</el-button> <el-button :type="processFlag === 3 ? 'primary' : 'text'" @click="processFlag = 3">入库历史</el-button> </div>--> </div> </div></template>
<script>import { getPurchaseOrderReceiptList, confirmQualifiedStorage, validateHandlingUnitForQualifiedStorage, getInboundHistory, validateLocationForPicking } from "@/api/po/po.js";import { filterRowsByAuthorizedSubSite, getAuthorizedSubSiteCodeList } from "@/utils/subSiteAuth.js";export default { data() { return { processFlag: 1, // 1-接收记录列表, 2-HandlingUnit扫描入库, 3-入库历史
scanCode: '', receiptList: [], historyList: [], selectedReceipt: {}, scannedItems: [], targetLocationId: '', isRemoveMode: false, loading: false, scanLoading: false, // 扫描HandlingUnit时的loading状态
loadingText: '处理中...', // loading提示文本
site: localStorage.getItem('site') }; }, methods: { handleBack() { if (this.processFlag === 1) { this.$router.back(); } else if (this.processFlag === 2) { this.processFlag = 1; this.resetData(); } else { this.processFlag = 1; } },
// 查询采购订单接收记录
searchReceiptList() { if (!this.scanCode.trim()) { return this.$message.error("请输入采购单号"); }
// 开始loading
this.loadingText = '查询中...'; this.loading = true;
const params = { purchaseOrderNo: this.scanCode.trim(), site: this.site+'%' };
getPurchaseOrderReceiptList(params).then(({ data }) => { if (data.code === 0) { const sourceRows = data.rows || []; const authorizedSubSiteCodeList = getAuthorizedSubSiteCodeList(this.$store.state.user.subSiteCodeList); // 接口按site前缀查询会返回同前缀下的所有子site,这里按当前用户授权子site做二次过滤
this.receiptList = filterRowsByAuthorizedSubSite(sourceRows, authorizedSubSiteCodeList, ['contract']); if (this.receiptList.length === 0) { this.$message.success("暂无To be Received状态的接收记录"); } } else { this.$message.error("查询失败"); } // 查询完成后让输入框失去焦点
this.$nextTick(() => { if (this.$refs.scanCodeRef) { this.$refs.scanCodeRef.blur(); } }); }).catch(error => { this.$message.error("查询失败"); console.error(error); // 查询失败时也让输入框失去焦点
this.$nextTick(() => { if (this.$refs.scanCodeRef) { this.$refs.scanCodeRef.blur(); } }); }).finally(() => { // 结束loading
this.loading = false; });
this.scanCode = ''; },
// 选择接收记录项目
selectReceiptItem(item) { this.selectedReceipt = { ...item }; this.processFlag = 2; this.$nextTick(() => { if (this.$refs.scanInput) { this.$refs.scanInput.focus(); } }); },
// 计算可用数量
getAvailableQty() { if (!this.selectedReceipt.qtyArrived) return 0; const arrived = parseFloat(this.selectedReceipt.qtyArrived) || 0; const scrapped = parseFloat(this.selectedReceipt.scrappedQty) || 0; const returned = parseFloat(this.selectedReceipt.returnedQty) || 0; return arrived - scrapped - returned; },
// 处理扫描
handleScan() { if (!this.scanCode.trim()) { return; }
if (this.isRemoveMode) { this.removeLabelByCode(this.scanCode.trim()); } else { this.validateAndAddLabel(this.scanCode.trim()); } this.scanCode = ''; },
// 处理库位扫描
handleLocationScan() { if (!this.targetLocationId.trim()) { return; }
// 校验库位类型
this.validateLocationForPickingType(); },
// 校验库位是否为PICKING类型
async validateLocationForPickingType() { if (!this.targetLocationId.trim()) { return; }
try { const { data } = await validateLocationForPicking({ site: this.site, locationId: this.targetLocationId.trim() });
if (data.code === 0) { // 校验通过,失去光标并定位到页面底部
if (this.$refs.locationInput) { this.$refs.locationInput.blur(); }
this.$nextTick(() => { const bottomActions = document.querySelector('.bottom-actions'); if (bottomActions) { bottomActions.scrollIntoView({ behavior: 'smooth', block: 'end' }); } }); } else { this.$message.error(data.msg || '库位必须是PICKING类型'); // 清空库位输入
this.targetLocationId = ''; // 重新聚焦到库位输入框
this.$nextTick(() => { if (this.$refs.locationInput) { this.$refs.locationInput.focus(); } }); } } catch (error) { console.error('库位校验失败:', error); this.$message.error('库位校验失败,请重试'); // 清空库位输入
this.targetLocationId = ''; // 重新聚焦到库位输入框
this.$nextTick(() => { if (this.$refs.locationInput) { this.$refs.locationInput.focus(); } }); } },
// 验证标签并添加到列表
validateAndAddLabel(unitId) { // 检查是否已经扫描过
const exists = this.scannedItems.find(item => item.unitId === unitId); if (exists) { this.$message.warning('该HandlingUnit已扫描,请勿重复扫描'); return; }
// 开始loading
this.scanLoading = true;
const params = { unitId: unitId, site: this.selectedReceipt.contract, expectedPartNo: this.selectedReceipt.sourcePartNo, expectedBatchNo: this.getBatchNoFromReceipt() // 从接收记录中获取期望的批次号
};
validateHandlingUnitForQualifiedStorage(params).then(({ data }) => { if (data && data.code === 0 && data.data) { const huInfo = data.data; this.processHandlingUnit(unitId, huInfo); } else { this.$message.error(data.msg || 'HandlingUnit校验失败'); } }).catch(error => { this.$message.error('HandlingUnit校验失败'); console.error(error); }).finally(() => { // 结束loading
this.scanLoading = false; }); },
// 从接收记录中获取批次号(如果有的话)
getBatchNoFromReceipt() { // 这里可能需要根据实际的接收记录结构来获取批次号
// 如果接收记录中没有批次号信息,可以返回空字符串,让后端从HandlingUnit中获取
return this.selectedReceipt.batchNo || ''; },
// 处理HandlingUnit数据
processHandlingUnit(unitId, huInfo) { // 所有校验都在后端完成,这里直接添加到列表
this.scannedItems.push({ id: Date.now(), unitId: unitId, partNo: huInfo.partNo, partDesc: huInfo.partDesc, qty: huInfo.qty, unit: huInfo.unit, batchNo: huInfo.batchNo, locationId: huInfo.locationId, wdr: huInfo.wdr });
this.$message.success('扫描成功'); },
// 通过条码移除标签
removeLabelByCode(unitId) { const index = this.scannedItems.findIndex(item => item.unitId === unitId); if (index !== -1) { this.scannedItems.splice(index, 1); this.$message.success('移除成功'); } else { this.$message.warning('未找到该HandlingUnit'); } },
// 确认入库
async confirmStorage() { // 验证必填字段
if (!this.targetLocationId) { this.$message.error('请输入目标库位'); return; }
if (this.scannedItems.length === 0) { this.$message.warning('请先扫描HandlingUnit'); return; }
// 提交前再次校验库位类型
try { const { data } = await validateLocationForPicking({ site: this.site, locationId: this.targetLocationId.trim() });
if (data.code !== 0) { this.$message.error(data.msg || '库位必须是PICKING类型'); return; } } catch (error) { console.error('库位校验失败:', error); this.$message.error('库位校验失败,请重试'); return; }
// 计算HandlingUnit总数量
const totalScannedQty = this.scannedItems.reduce((sum, item) => sum + (parseFloat(item.qty) || 0), 0); const availableQty = this.getAvailableQty();
if (totalScannedQty > availableQty) { this.$message.error('扫描的HandlingUnit总数量不能大于可用数量'); return; }
this.$confirm('确认要进行检验合格入库操作吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => { this.submitConfirmStorage(); }).catch(() => { // 用户取消
}); },
// 提交确认入库
submitConfirmStorage() { const handlingUnitIds = this.scannedItems.map(item => item.unitId); const totalQty = this.scannedItems.reduce((sum, item) => sum + (parseFloat(item.qty) || 0), 0);
const params = { site: this.selectedReceipt.contract, fuSite: localStorage.getItem('site'), receiptSequence: this.selectedReceipt.receiptSequence, sourceRef1: this.selectedReceipt.sourceRef1, sourceRef2: this.selectedReceipt.sourceRef2, sourceRef3: this.selectedReceipt.sourceRef3, sourceRef4: this.selectedReceipt.sourceRef4, receiptNo: this.selectedReceipt.receiptNo, partNo: this.selectedReceipt.sourcePartNo, locationNo: '', // 后端会从HandlingUnit中获取
lotBatchNo: '', // 后端会从HandlingUnit中获取
wdr: '', // 后端会从HandlingUnit中获取
engChgLevel: this.selectedReceipt.engChgLevel || '1', uom: this.selectedReceipt.uom || '', toLocationNo: this.targetLocationId, qtyToMove: totalQty, qtyArrived: this.selectedReceipt.qtyArrived, scrappedQty: this.selectedReceipt.scrappedQty || 0, returnedQty: this.selectedReceipt.returnedQty || 0, handlingUnitIds: handlingUnitIds };
// 开始loading
this.loadingText = '入库中...'; this.loading = true;
// 调用后端API
confirmQualifiedStorage(params).then(({ data }) => { if (data && data.code === 0) { this.$message({ message: '检验合格入库成功!处理单元: ' + handlingUnitIds.length + '个', type: 'success', duration: 3000 });
// 清空页面内容,回到列表页面
this.resetData(); this.processFlag = 1; } else { this.$message.error(data.msg || '检验合格入库失败'); } }).catch(error => { console.error('检验合格入库失败:', error); this.$message.error('检验合格入库失败,请重试'); }).finally(() => { // 结束loading
this.loading = false; }); },
// 查询入库历史
searchInboundHistory() { const params = { site: this.site };
getInboundHistory(params).then(({ data }) => { if (data.code === 0) { this.historyList = data.rows || []; if (this.historyList.length === 0) { this.$message.info("暂无入库历史记录"); } } else { this.$message.error(data.msg || "查询失败"); } }).catch(error => { this.$message.error("查询失败"); console.error(error); }); },
// 重置数据
resetData() { this.selectedReceipt = {}; this.scannedItems = []; this.targetLocationId = ''; this.isRemoveMode = false; this.scanCode = ''; },
// 格式化日期
formatDate(date) { if (!date) return ''; const d = new Date(date); return d.getFullYear() + '-' + String(d.getMonth() + 1).padStart(2, '0') + '-' + String(d.getDate()).padStart(2, '0'); } },
mounted() { this.$nextTick(() => { if (this.$refs.scanCodeRef) { this.$refs.scanCodeRef.focus(); } }); }};</script>
<style scoped>/* 复用inventory-move.vue的样式 */.pda-container { width: 100%; height: 100vh; display: flex; flex-direction: column; overflow: hidden;}
.status-bar { background: #17B3A3; color: white; padding: 8px 16px; display: flex; justify-content: space-between; align-items: center; height: 40px; min-height: 40px;}
.goBack { cursor: pointer; font-size: 16px; font-weight: 500;}
.scan-box input { width: 100%; padding: 12px; font-size: 16px;}
/* 物料描述样式 - 防止重叠 */.description-col { margin-bottom: 15px !important;}
.part-description { word-wrap: break-word; word-break: break-all; line-height: 1.8; display: block; max-width: 100%; margin-bottom: 10px; padding-bottom: 5px;}
/* 确保物料描述的form-item有足够间距 */.description-col .el-form-item { margin-bottom: 15px !important;}
/* 搜索容器 */.search-container { padding: 12px 16px; background: white; display: flex; align-items: center; gap: 12px;}
.search-container .el-input { width: 240px; margin-right: 12px;}
/* 紧凑型输入框样式 */.compact-input >>> .el-input__inner { height: 36px; padding: 0 12px 0 35px; font-size: 14px;}
.compact-input >>> .el-input__prefix { left: 10px;}
.compact-input >>> .el-input__suffix { right: 30px;}
/* 模式切换开关 */.mode-switch { position: relative; display: inline-block;}
.custom-switch { transform: scale(1.3);}
/* 中间文字 */.switch-text { position: absolute; left: 25%; transform: translateX(-50%); top: 50%; transform: translateY(-50%) translateX(-50%); font-size: 12px; font-weight: 500; color: #606266; white-space: nowrap; pointer-events: none; z-index: 1; top: 53%; transform: translate(-50%, -50%); font-size: 12px; font-weight: bold; color: white; pointer-events: none; z-index: 2;}
.switch-text2 { position: absolute; left: 75%; transform: translateX(-50%); top: 50%; transform: translateY(-50%) translateX(-50%); font-size: 12px; font-weight: 500; color: #606266; white-space: nowrap; pointer-events: none; z-index: 1; top: 53%; transform: translate(-50%, -50%); font-size: 12px; font-weight: bold; color: white; pointer-events: none; z-index: 2;}
/* 调整 switch 尺寸以便容纳文字 */.custom-switch >>> .el-switch__core { width: 60px; height: 22px;}
/* 物料信息卡片 */.material-info-card { background: white; margin: 4px 4px; padding: 6px 20px; border-radius: 8px; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); border: 1px solid #f0f0f0;}
.card-title { margin-bottom: 8px; display: flex; align-items: center; gap: 8px;}
.title-label { font-size: 12px; color: #666; font-weight: 500;}
.title-value { font-size: 16px; font-weight: bold; color: #333; line-height: 1.2;}
/* 表单样式 */.form-row { display: flex; gap: 12px; margin-bottom: 12px;}
.form-row:last-child { margin-bottom: 0;}
.form-item { flex: 1; display: flex; flex-direction: column;}
.form-label { font-size: 11px; color: #666; font-weight: 500; margin-bottom: 4px; display: block;}
.form-item .el-input { width: 100%;}
.form-item .el-date-editor { width: 100%;}
/* 区域标题 */.section-title { display: flex; align-items: center; justify-content: space-between; padding: 6px 8px; background: white; margin: 0 4px; margin-top: 4px; border-radius: 8px 8px 0 0; border-bottom: 2px solid #17B3A3;}
.title-left { display: flex; align-items: center;}
.title-left i { color: #17B3A3; font-size: 16px; margin-right: 8px;}
.title-left span { color: #17B3A3; font-size: 14px; font-weight: 500;}
/* 标签列表 */.label-list { background: white; margin: 4px 4px; border-radius: 0 0 8px 8px; overflow: hidden;}
.label-list .el-form-item { margin-bottom: 1px;}
.label-list .el-form-item__label { padding-bottom: 1px; margin-bottom: 0; line-height: 1.1; font-size: 11px;}
.label-list .el-form-item__content { line-height: 1.2; font-size: 12px;}
.item-list { flex: 1; overflow-y: auto; margin: 10px 0; border: 1px solid rgba(200, 200, 200, 0.8); background: white;}
.item-list span { color: #000; font-size: 15px;}
.bottom-line-row { border-bottom: 1px solid #f0f0f0; margin-bottom: 8px; padding-bottom: 8px;}
.inboundButton { font-size: 16px; border-radius: 3px; color: #17b3a3;}
.item-list .el-row { cursor: pointer; transition: background 0.3s; padding: 10px;}
.item-list .el-row:hover { background: #f5f7fa;}
.empty-labels { padding: 20px; text-align: center; color: #999; background: white; margin: 0 4px; border-radius: 8px;}
/* 底部操作按钮 */.bottom-actions { display: flex; padding: 16px; gap: 20px; background: white; margin-top: auto;}
.action-btn { flex: 1; padding: 12px; border: 1px solid #17B3A3; background: #17B3A3; color: white; border-radius: 20px; font-size: 14px; cursor: pointer; transition: all 0.2s ease;}
.action-btn.secondary { background: white; color: #17B3A3;}
.action-btn:hover { background: #0d8f7f; border-color: #0d8f7f;}
.action-btn.secondary:hover { background: #17B3A3; color: white;}
.action-btn:active { transform: scale(0.98);}
.action-btn:disabled { background: #c0c4cc !important; border-color: #c0c4cc !important; color: white !important; cursor: not-allowed !important; transform: none !important; box-shadow: none !important;}
.action-btn:disabled:hover { background: #c0c4cc !important; transform: none !important; box-shadow: none !important;}
.action-btn.secondary:disabled { background: #f5f7fa !important; color: #c0c4cc !important; border-color: #e4e7ed !important;}
/* 全页面Loading样式 */.page-loading-overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(255, 255, 255, 0.5); display: flex; align-items: center; justify-content: center; z-index: 9999;}
.page-loading-content { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 30px; background: white; border-radius: 12px; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); min-width: 150px;}
.page-loading-icon { font-size: 32px; color: #17B3A3; animation: rotating 1s linear infinite; margin-bottom: 16px;}
.page-loading-text { color: #17B3A3; font-size: 16px; font-weight: 500; text-align: center;}
.content-disabled { pointer-events: none; opacity: 0.6;}
@keyframes rotating { from { transform: rotate(0deg); } to { transform: rotate(360deg); }}
/* 响应式设计 */@media (max-width: 360px) { .status-bar { padding: 8px 12px; }
.search-container { padding: 8px 12px; margin: 1px 4px; }
.material-info-card { margin: 4px 4px; padding: 6px 16px; }
.item-list { margin: 0 12px 8px; }
.form-row { gap: 8px; margin-bottom: 8px; }
.form-label { font-size: 10px; margin-bottom: 2px; }}</style>
|