|
|
|
@ -23,6 +23,7 @@ |
|
|
|
class="form-input" |
|
|
|
style="flex: 0.75;" |
|
|
|
clearable |
|
|
|
@focus.native="$event.target.setAttribute('inputmode', 'none')" |
|
|
|
@keyup.enter.native="handlePalletScan" |
|
|
|
ref="palletInput" |
|
|
|
/> |
|
|
|
@ -111,6 +112,7 @@ |
|
|
|
<button |
|
|
|
class="action-btn secondary" |
|
|
|
style="flex: 0.25; margin: 0; white-space: nowrap;" |
|
|
|
:disabled="currentPalletType === ''" |
|
|
|
@click="showScanModal" |
|
|
|
> |
|
|
|
扫描条码 |
|
|
|
@ -191,7 +193,7 @@ |
|
|
|
<button class="action-btn secondary" style="margin-left: 10px;" @click="detailModalVisible=false">取消</button> |
|
|
|
</div> |
|
|
|
</el-dialog> |
|
|
|
<!-- 扫码模态框 --> |
|
|
|
<!-- 扫码模态框 - rqrq --> |
|
|
|
<el-dialog |
|
|
|
title="扫描标签" |
|
|
|
:visible.sync="scanModalVisible" |
|
|
|
@ -203,43 +205,54 @@ |
|
|
|
:append-to-body="true" |
|
|
|
> |
|
|
|
<div class="scan-modal-content"> |
|
|
|
<!-- 扫进时显示位置和层数选择 --> |
|
|
|
<!-- 扫进时显示层数选择和位置网格 - rqrq --> |
|
|
|
<div v-if="operationType === 'in'" class="modal-form"> |
|
|
|
<div class="input-group"> |
|
|
|
<label class="input-label">位置</label> |
|
|
|
<el-select |
|
|
|
v-model="scanPosition" |
|
|
|
placeholder="请选择位置" |
|
|
|
style="width: 100%;" |
|
|
|
@change="handleScanPositionChange" |
|
|
|
> |
|
|
|
<el-option |
|
|
|
v-for="position in positionOptions" |
|
|
|
:key="position" |
|
|
|
:label="position" |
|
|
|
:value="position" |
|
|
|
/> |
|
|
|
</el-select> |
|
|
|
</div> |
|
|
|
<div class="input-group"> |
|
|
|
<label class="input-label">层数</label> |
|
|
|
<el-select |
|
|
|
v-model="scanLayer" |
|
|
|
placeholder="请选择层数" |
|
|
|
@change="moveFocusToScanInput" |
|
|
|
style="width: 100%;" |
|
|
|
> |
|
|
|
<el-option |
|
|
|
<!-- 层数选择(混装托盘不显示) - rqrq --> |
|
|
|
<div v-if="!currentMixedMode && scanLayerOptions.length > 0" class="input-group"> |
|
|
|
<label class="input-label">层数(当前选择:第{{ scanLayer }}层)</label> |
|
|
|
<div class="layer-grid"> |
|
|
|
<div |
|
|
|
v-for="layer in scanLayerOptions" |
|
|
|
:key="layer" |
|
|
|
:label="`第${layer}层`" |
|
|
|
:value="layer" |
|
|
|
/> |
|
|
|
</el-select> |
|
|
|
class="layer-item" |
|
|
|
:class="{ |
|
|
|
'layer-selected': scanLayer === layer |
|
|
|
}" |
|
|
|
@click="handleLayerClick(layer)" |
|
|
|
> |
|
|
|
{{ layer }} |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
<!-- 位置网格选择器 - rqrq --> |
|
|
|
<div class="input-group"> |
|
|
|
<label class="input-label"> |
|
|
|
位置{{ currentSelectedPosition ? `(当前选择:${currentSelectedPosition})` : '' }} |
|
|
|
<span v-if="positionGridLoading" style="color: #909399; font-size: 12px;">(加载中...)</span> |
|
|
|
</label> |
|
|
|
<div class="position-grid" :class="[ |
|
|
|
{'position-grid-loading': positionGridLoading}, |
|
|
|
positionGrid.length === 4 ? 'position-grid-4' : 'position-grid-9' |
|
|
|
]"> |
|
|
|
<div |
|
|
|
v-for="(position, index) in positionGrid" |
|
|
|
:key="index" |
|
|
|
class="position-item" |
|
|
|
:class="{ |
|
|
|
'position-disabled': positionGridLoading || !availablePositions.includes(position), |
|
|
|
'position-selected': currentSelectedPosition === position, |
|
|
|
'position-loading': positionGridLoading |
|
|
|
}" |
|
|
|
@click="handlePositionClick(position)" |
|
|
|
> |
|
|
|
{{ position }} |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
<!-- 标签扫描 --> |
|
|
|
<!-- 标签扫描 - rqrq --> |
|
|
|
<div class="input-group"> |
|
|
|
<label class="input-label">标签二维码</label> |
|
|
|
<el-input |
|
|
|
@ -247,7 +260,9 @@ |
|
|
|
placeholder="请扫描标签二维码" |
|
|
|
class="form-input" |
|
|
|
clearable |
|
|
|
:disabled="operationType === 'in' && !currentSelectedPosition" |
|
|
|
@keyup.enter.native="handleLabelScan" |
|
|
|
@focus.native="$event.target.setAttribute('inputmode', 'none')" |
|
|
|
ref="scanInput" |
|
|
|
/> |
|
|
|
</div> |
|
|
|
@ -456,7 +471,8 @@ import { |
|
|
|
getPalletInfo, |
|
|
|
getPalletTypeList, |
|
|
|
getPalletTypeAreas, |
|
|
|
updatePalletTypeAndAutoSort |
|
|
|
updatePalletTypeAndAutoSort, |
|
|
|
getAvailablePositionsForLayer |
|
|
|
} from '../../../api/automatedWarehouse/palletPacking' |
|
|
|
|
|
|
|
export default { |
|
|
|
@ -483,14 +499,21 @@ export default { |
|
|
|
positionOptions: [], |
|
|
|
layerOptions: [], |
|
|
|
|
|
|
|
// 扫码模态框 |
|
|
|
// 扫码模态框 - rqrq |
|
|
|
scanModalVisible: false, |
|
|
|
scanCode: '', |
|
|
|
scanPosition: '', |
|
|
|
scanLayer: '', |
|
|
|
scanLayer: 1, |
|
|
|
scanLayerOptions: [], |
|
|
|
needRefreshOnClose: false, // 标记是否需要在关闭模态框时刷新 |
|
|
|
|
|
|
|
// 位置网格数据 - rqrq |
|
|
|
positionGrid: [], // 位置网格列表(用于显示4宫格或9宫格) |
|
|
|
availablePositions: [], // 可用位置列表 |
|
|
|
currentSelectedPosition: '', // 当前选中的位置 |
|
|
|
currentMixedMode: false, // 是否混装模式 |
|
|
|
positionGridLoading: false, // 位置网格加载中 |
|
|
|
|
|
|
|
// 栈板明细 |
|
|
|
detailList: [], |
|
|
|
|
|
|
|
@ -586,7 +609,7 @@ export default { |
|
|
|
console.log('页面已重置到初始状态'); |
|
|
|
}, |
|
|
|
|
|
|
|
// 扫描栈板 |
|
|
|
// 扫描栈板 - rqrq |
|
|
|
handlePalletScan() { |
|
|
|
if (!this.palletCode.trim()) { |
|
|
|
this.$message.error('请输入栈板编码'); |
|
|
|
@ -609,11 +632,41 @@ export default { |
|
|
|
this.refreshTable(); |
|
|
|
}) |
|
|
|
} else { |
|
|
|
this.$message.error(data.msg || '栈板不存在'); |
|
|
|
// 失败:弹出提示框,截取前100字符 - rqrq |
|
|
|
let errorMsg = data.msg || '栈板不存在'; |
|
|
|
if (errorMsg.length > 100) { |
|
|
|
errorMsg = errorMsg.substring(0, 100) + '...'; |
|
|
|
} |
|
|
|
this.$alert(errorMsg, '错误', { |
|
|
|
confirmButtonText: '确定', |
|
|
|
callback: () => { |
|
|
|
this.palletCode = ''; |
|
|
|
this.$nextTick(() => { |
|
|
|
if (this.$refs.palletInput) { |
|
|
|
this.$refs.palletInput.focus(); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
}).catch(error => { |
|
|
|
console.error('验证栈板失败:', error); |
|
|
|
this.$message.error('验证栈板失败'); |
|
|
|
// 网络错误:弹出提示框 - rqrq |
|
|
|
let errorMsg = error.message || '验证栈板失败'; |
|
|
|
if (errorMsg.length > 100) { |
|
|
|
errorMsg = errorMsg.substring(0, 100) + '...'; |
|
|
|
} |
|
|
|
this.$alert(errorMsg, '错误', { |
|
|
|
confirmButtonText: '确定', |
|
|
|
callback: () => { |
|
|
|
this.palletCode = ''; |
|
|
|
this.$nextTick(() => { |
|
|
|
if (this.$refs.palletInput) { |
|
|
|
this.$refs.palletInput.focus(); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
}); |
|
|
|
}); |
|
|
|
}, |
|
|
|
|
|
|
|
@ -843,15 +896,135 @@ export default { |
|
|
|
}); |
|
|
|
}, |
|
|
|
|
|
|
|
// 显示扫码模态框 |
|
|
|
// 显示扫码模态框 - rqrq |
|
|
|
showScanModal() { |
|
|
|
this.scanModalVisible = true; |
|
|
|
this.scanCode = ''; |
|
|
|
this.scanPosition = ''; |
|
|
|
this.scanLayer = ''; |
|
|
|
this.scanLayerOptions = []; |
|
|
|
this.needRefreshOnClose = false; // 重置刷新标记 |
|
|
|
this.currentSelectedPosition = ''; |
|
|
|
this.needRefreshOnClose = false; |
|
|
|
|
|
|
|
// 初始化层数和位置网格 - rqrq |
|
|
|
if (this.operationType === 'in') { |
|
|
|
this.scanLayer = 1; |
|
|
|
// 先查询当前栈板已有的最大层数,动态生成层数选项 - rqrq |
|
|
|
this.loadLayerOptions(); |
|
|
|
} else { |
|
|
|
// 扫出操作,直接聚焦到输入框 - rqrq |
|
|
|
this.$nextTick(() => { |
|
|
|
if (this.$refs.scanInput) { |
|
|
|
this.$refs.scanInput.focus(); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
// 加载层数选项 - rqrq |
|
|
|
loadLayerOptions() { |
|
|
|
console.log('开始加载层数选项 - rqrq,maxLayer=' + this.currentMaxLayer); |
|
|
|
|
|
|
|
getPalletDetails({ |
|
|
|
site: this.site, |
|
|
|
palletId: this.palletCode, |
|
|
|
position: '', |
|
|
|
layer: null |
|
|
|
}).then(({ data }) => { |
|
|
|
if (data && data.code === 0) { |
|
|
|
const details = data.details || []; |
|
|
|
|
|
|
|
// 获取当前已有的最大层数 - rqrq |
|
|
|
let maxExistingLayer = 0; |
|
|
|
if (details.length > 0) { |
|
|
|
maxExistingLayer = Math.max(...details.map(d => d.layer || 0)); |
|
|
|
} |
|
|
|
|
|
|
|
// 根据maxLayer判断 - rqrq |
|
|
|
if (this.currentMaxLayer === 0) { |
|
|
|
// maxLayer=0:不限高,可选层数为已有最大层+1层 - rqrq |
|
|
|
this.currentMixedMode = false; |
|
|
|
this.scanLayerOptions = Array.from({ length: maxExistingLayer + 1 }, (_, i) => i + 1); |
|
|
|
console.log('不限高模式 - 已有最大层:' + maxExistingLayer + ',可选层数:' + this.scanLayerOptions.length + ' - rqrq'); |
|
|
|
} else { |
|
|
|
// maxLayer>0:有限高,可选1~maxLayer层 - rqrq |
|
|
|
this.currentMixedMode = false; |
|
|
|
this.scanLayerOptions = Array.from({ length: this.currentMaxLayer }, (_, i) => i + 1); |
|
|
|
console.log('限高模式 - maxLayer:' + this.currentMaxLayer + ' - rqrq'); |
|
|
|
} |
|
|
|
|
|
|
|
// 加载位置网格 - rqrq |
|
|
|
this.loadAvailablePositions(); |
|
|
|
} else { |
|
|
|
this.$message.error(data.msg || '获取栈板信息失败'); |
|
|
|
} |
|
|
|
}).catch(error => { |
|
|
|
console.error('获取栈板信息失败:', error); |
|
|
|
this.$message.error('获取栈板信息失败'); |
|
|
|
}); |
|
|
|
}, |
|
|
|
|
|
|
|
// 加载可用位置 - rqrq |
|
|
|
loadAvailablePositions() { |
|
|
|
console.log('开始加载位置网格 - rqrq,layer=' + this.scanLayer); |
|
|
|
|
|
|
|
// 设置加载状态,禁用所有位置 - rqrq |
|
|
|
this.positionGridLoading = true; |
|
|
|
this.availablePositions = []; // 清空可用位置,全部禁用 |
|
|
|
|
|
|
|
getAvailablePositionsForLayer({ |
|
|
|
site: this.site, |
|
|
|
palletId: this.palletCode, |
|
|
|
layer: this.scanLayer |
|
|
|
}).then(({ data }) => { |
|
|
|
if (data && data.code === 0) { |
|
|
|
const result = data.data; |
|
|
|
this.positionGrid = result.positions || []; |
|
|
|
this.availablePositions = result.availablePositions || []; |
|
|
|
console.log('位置网格加载完成 - 总位置:' + this.positionGrid.length + ',可用:' + this.availablePositions.length + ' - rqrq'); |
|
|
|
} else { |
|
|
|
this.$message.error(data.msg || '获取位置信息失败'); |
|
|
|
// 失败后保持全部禁用 - rqrq |
|
|
|
this.availablePositions = []; |
|
|
|
} |
|
|
|
}).catch(error => { |
|
|
|
console.error('获取位置信息失败:', error); |
|
|
|
this.$message.error('获取位置信息失败'); |
|
|
|
// 失败后保持全部禁用 - rqrq |
|
|
|
this.availablePositions = []; |
|
|
|
}).finally(() => { |
|
|
|
// 无论成功失败,都要解除加载状态 - rqrq |
|
|
|
this.positionGridLoading = false; |
|
|
|
}); |
|
|
|
}, |
|
|
|
|
|
|
|
// 点击层数格子 - rqrq |
|
|
|
handleLayerClick(layer) { |
|
|
|
if (this.scanLayer === layer) { |
|
|
|
return; // 已选中,不重复处理 |
|
|
|
} |
|
|
|
|
|
|
|
console.log('切换层数 - rqrq,从第' + this.scanLayer + '层切换到第' + layer + '层'); |
|
|
|
this.scanLayer = layer; |
|
|
|
this.currentSelectedPosition = ''; |
|
|
|
this.loadAvailablePositions(); |
|
|
|
}, |
|
|
|
|
|
|
|
// 点击位置网格 - rqrq |
|
|
|
handlePositionClick(position) { |
|
|
|
// 加载中或位置不可用时不处理 - rqrq |
|
|
|
if (this.positionGridLoading) { |
|
|
|
this.$message.warning('位置信息加载中,请稍候'); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (!this.availablePositions.includes(position)) { |
|
|
|
this.$message.warning('该位置不可用'); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
this.currentSelectedPosition = position; |
|
|
|
this.scanPosition = position; |
|
|
|
console.log('选择位置 - rqrq,position=' + position); |
|
|
|
|
|
|
|
// 聚焦到扫描输入框 - rqrq |
|
|
|
this.$nextTick(() => { |
|
|
|
if (this.$refs.scanInput) { |
|
|
|
this.$refs.scanInput.focus(); |
|
|
|
@ -875,44 +1048,9 @@ export default { |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
// 扫码模态框中位置变化 |
|
|
|
handleScanPositionChange() { |
|
|
|
if (this.scanPosition) { |
|
|
|
// maxLayer=0表示混装托盘,只能选第1层 |
|
|
|
if (this.currentMaxLayer === 0) { |
|
|
|
this.scanLayerOptions = [1]; |
|
|
|
this.scanLayer = 1; // 自动选中第1层 |
|
|
|
this.moveFocusToScanInput(); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// maxLayer>0,根据已有层数和maxLayer计算可选层数 |
|
|
|
getLayersByPosition({ |
|
|
|
site: this.site, |
|
|
|
palletId: this.palletCode, |
|
|
|
position: this.scanPosition |
|
|
|
}).then(({ data }) => { |
|
|
|
if (data.code === 0) { |
|
|
|
const existingMaxLayer = data.layers && data.layers.length > 0 |
|
|
|
? Math.max(...data.layers) |
|
|
|
: 0; |
|
|
|
|
|
|
|
// 有maxLayer限制,取已有最大层+1和maxLayer的较小值 |
|
|
|
const layerCount = Math.min(existingMaxLayer + 1, this.currentMaxLayer); |
|
|
|
|
|
|
|
this.scanLayerOptions = Array.from({ length: layerCount }, (_, i) => i + 1); |
|
|
|
} |
|
|
|
}).catch(error => { |
|
|
|
console.error('获取层数失败:', error); |
|
|
|
this.scanLayerOptions = [1]; |
|
|
|
}); |
|
|
|
} else { |
|
|
|
this.scanLayerOptions = []; |
|
|
|
} |
|
|
|
this.scanLayer = ''; |
|
|
|
}, |
|
|
|
|
|
|
|
// 处理标签扫描 |
|
|
|
// 处理标签扫描 - rqrq |
|
|
|
handleLabelScan() { |
|
|
|
if (!this.scanCode.trim()) { |
|
|
|
this.$message.error('请输入标签编码'); |
|
|
|
@ -939,16 +1077,50 @@ export default { |
|
|
|
}).then(({ data }) => { |
|
|
|
if (data.code === 0) { |
|
|
|
this.$message.success('扫进成功'); |
|
|
|
this.needRefreshOnClose = true; // 标记需要在关闭时刷新 |
|
|
|
this.scanCode = ''; // 清空扫描码,准备下次扫描 |
|
|
|
this.handleScanPositionChange() |
|
|
|
this.needRefreshOnClose = true; |
|
|
|
this.scanCode = ''; |
|
|
|
|
|
|
|
// 重新加载层数选项(可能新增了层数) - rqrq |
|
|
|
this.loadLayerOptions(); |
|
|
|
|
|
|
|
// 保持当前位置选中,聚焦到输入框 - rqrq |
|
|
|
this.$refs.scanInput.focus(); |
|
|
|
} else { |
|
|
|
this.$message.error(data.msg || '扫进失败'); |
|
|
|
// 扫进失败:弹出提示框,截取前100字符 - rqrq |
|
|
|
let errorMsg = data.msg || '扫进失败'; |
|
|
|
if (errorMsg.length > 100) { |
|
|
|
errorMsg = errorMsg.substring(0, 100) + '...'; |
|
|
|
} |
|
|
|
this.$alert(errorMsg, '错误', { |
|
|
|
confirmButtonText: '确定', |
|
|
|
callback: () => { |
|
|
|
this.scanCode = ''; |
|
|
|
this.$nextTick(() => { |
|
|
|
if (this.$refs.scanInput) { |
|
|
|
this.$refs.scanInput.focus(); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
}).catch(error => { |
|
|
|
console.error('扫进失败:', error); |
|
|
|
this.$message.error('扫进失败'); |
|
|
|
// 网络错误:弹出提示框 - rqrq |
|
|
|
let errorMsg = error.message || '扫进失败'; |
|
|
|
if (errorMsg.length > 100) { |
|
|
|
errorMsg = errorMsg.substring(0, 100) + '...'; |
|
|
|
} |
|
|
|
this.$alert(errorMsg, '错误', { |
|
|
|
confirmButtonText: '确定', |
|
|
|
callback: () => { |
|
|
|
this.scanCode = ''; |
|
|
|
this.$nextTick(() => { |
|
|
|
if (this.$refs.scanInput) { |
|
|
|
this.$refs.scanInput.focus(); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
}); |
|
|
|
}); |
|
|
|
} else { |
|
|
|
// 扫出操作 |
|
|
|
@ -959,15 +1131,45 @@ export default { |
|
|
|
}).then(({ data }) => { |
|
|
|
if (data.code === 0) { |
|
|
|
this.$message.success('扫出成功'); |
|
|
|
this.needRefreshOnClose = true; // 标记需要在关闭时刷新 |
|
|
|
this.scanCode = ''; // 清空扫描码,准备下次扫描 |
|
|
|
this.needRefreshOnClose = true; |
|
|
|
this.scanCode = ''; |
|
|
|
this.$refs.scanInput.focus(); |
|
|
|
} else { |
|
|
|
this.$message.error(data.msg || '扫出失败'); |
|
|
|
// 扫出失败:弹出提示框,截取前100字符 - rqrq |
|
|
|
let errorMsg = data.msg || '扫出失败'; |
|
|
|
if (errorMsg.length > 100) { |
|
|
|
errorMsg = errorMsg.substring(0, 100) + '...'; |
|
|
|
} |
|
|
|
this.$alert(errorMsg, '错误', { |
|
|
|
confirmButtonText: '确定', |
|
|
|
callback: () => { |
|
|
|
this.scanCode = ''; |
|
|
|
this.$nextTick(() => { |
|
|
|
if (this.$refs.scanInput) { |
|
|
|
this.$refs.scanInput.focus(); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
}).catch(error => { |
|
|
|
console.error('扫出失败:', error); |
|
|
|
this.$message.error('扫出失败'); |
|
|
|
// 网络错误:弹出提示框 - rqrq |
|
|
|
let errorMsg = error.message || '扫出失败'; |
|
|
|
if (errorMsg.length > 100) { |
|
|
|
errorMsg = errorMsg.substring(0, 100) + '...'; |
|
|
|
} |
|
|
|
this.$alert(errorMsg, '错误', { |
|
|
|
confirmButtonText: '确定', |
|
|
|
callback: () => { |
|
|
|
this.scanCode = ''; |
|
|
|
this.$nextTick(() => { |
|
|
|
if (this.$refs.scanInput) { |
|
|
|
this.$refs.scanInput.focus(); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
}, |
|
|
|
@ -1381,4 +1583,117 @@ export default { |
|
|
|
background-color: #ccc !important; |
|
|
|
border-color: #ccc !important; |
|
|
|
} |
|
|
|
|
|
|
|
/* 层数网格样式 - rqrq */ |
|
|
|
.layer-grid { |
|
|
|
display: flex; |
|
|
|
flex-wrap: wrap; |
|
|
|
gap: 8px; |
|
|
|
margin-top: 8px; |
|
|
|
} |
|
|
|
|
|
|
|
.layer-item { |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
|
justify-content: center; |
|
|
|
min-width: 50px; |
|
|
|
height: 45px; |
|
|
|
padding: 0 12px; |
|
|
|
background-color: #fff; |
|
|
|
border: 2px solid #dcdfe6; |
|
|
|
border-radius: 6px; |
|
|
|
font-size: 15px; |
|
|
|
font-weight: bold; |
|
|
|
cursor: pointer; |
|
|
|
transition: all 0.3s; |
|
|
|
user-select: none; |
|
|
|
} |
|
|
|
|
|
|
|
.layer-item:hover { |
|
|
|
border-color: #409eff; |
|
|
|
background-color: #ecf5ff; |
|
|
|
} |
|
|
|
|
|
|
|
.layer-item.layer-selected { |
|
|
|
border-color: #409eff; |
|
|
|
background-color: #409eff; |
|
|
|
color: #fff; |
|
|
|
} |
|
|
|
|
|
|
|
/* 位置网格样式 - rqrq */ |
|
|
|
.position-grid { |
|
|
|
display: grid; |
|
|
|
gap: 10px; |
|
|
|
margin-top: 8px; |
|
|
|
position: relative; |
|
|
|
} |
|
|
|
|
|
|
|
/* 4宫格:2行2列,按列排列(1,2 | 3,4) - rqrq */ |
|
|
|
.position-grid.position-grid-4 { |
|
|
|
grid-template-columns: repeat(2, 1fr); |
|
|
|
grid-template-rows: repeat(2, 1fr); |
|
|
|
grid-auto-flow: column; |
|
|
|
} |
|
|
|
|
|
|
|
/* 9宫格:3行3列,按列排列(1,2,3 | 4,5,6 | 7,8,9) - rqrq */ |
|
|
|
.position-grid.position-grid-9 { |
|
|
|
grid-template-columns: repeat(3, 1fr); |
|
|
|
grid-template-rows: repeat(3, 1fr); |
|
|
|
grid-auto-flow: column; |
|
|
|
} |
|
|
|
|
|
|
|
/* 加载中的遮罩效果 - rqrq */ |
|
|
|
.position-grid.position-grid-loading { |
|
|
|
opacity: 0.7; |
|
|
|
pointer-events: none; |
|
|
|
} |
|
|
|
|
|
|
|
.position-item { |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
|
justify-content: center; |
|
|
|
height: 60px; |
|
|
|
background-color: #fff; |
|
|
|
border: 2px solid #dcdfe6; |
|
|
|
border-radius: 6px; |
|
|
|
font-size: 16px; |
|
|
|
font-weight: bold; |
|
|
|
cursor: pointer; |
|
|
|
transition: all 0.3s; |
|
|
|
user-select: none; |
|
|
|
} |
|
|
|
|
|
|
|
.position-item:hover:not(.position-disabled) { |
|
|
|
border-color: #409eff; |
|
|
|
background-color: #ecf5ff; |
|
|
|
} |
|
|
|
|
|
|
|
.position-item.position-selected { |
|
|
|
border-color: #409eff; |
|
|
|
background-color: #409eff; |
|
|
|
color: #fff; |
|
|
|
} |
|
|
|
|
|
|
|
.position-item.position-disabled { |
|
|
|
background-color: #f5f7fa; |
|
|
|
color: #c0c4cc; |
|
|
|
cursor: not-allowed; |
|
|
|
opacity: 0.6; |
|
|
|
} |
|
|
|
|
|
|
|
/* 加载中的位置项样式 - rqrq */ |
|
|
|
.position-item.position-loading { |
|
|
|
background: linear-gradient(90deg, #f5f7fa 25%, #e4e7ed 50%, #f5f7fa 75%); |
|
|
|
background-size: 200% 100%; |
|
|
|
animation: loading 1.5s ease-in-out infinite; |
|
|
|
} |
|
|
|
|
|
|
|
@keyframes loading { |
|
|
|
0% { |
|
|
|
background-position: 200% 0; |
|
|
|
} |
|
|
|
100% { |
|
|
|
background-position: -200% 0; |
|
|
|
} |
|
|
|
} |
|
|
|
</style> |