<template>
|
<view class="sockpage">
|
<view class="column">
|
<!-- 托盘编码 -->
|
<view class="form-card">
|
<view class="form-row">
|
<view class="label">
|
<text class="required">*</text>托盘编码:
|
</view>
|
<view class="picker-wrap">
|
<view class="input-box">
|
<input
|
type="text"
|
v-model="barcode"
|
placeholder="请扫码"
|
placeholder-class="input-placeholder"
|
/>
|
</view>
|
</view>
|
</view>
|
</view>
|
|
<!-- 箱型选择 -->
|
<view class="form-card">
|
<view class="form-row">
|
<view class="label">
|
<text class="required">*</text>箱型:
|
</view>
|
<view class="picker-wrap">
|
<picker @change="modePickerChange" :value="index_mode" :range="mode">
|
<view class="input-box">
|
<text class="input-placeholder" v-if="!mode.length || !mode[index_mode]">请选择箱型</text>
|
<text class="input-value" v-else>{{mode[index_mode]}}</text>
|
</view>
|
</picker>
|
</view>
|
</view>
|
</view>
|
|
<!-- 物料码扫码(隐藏但可用) -->
|
<!-- <view class="form-card" style="height: 0; overflow: hidden; padding: 0; margin: 0;"> -->
|
<view class="form-card" style=" overflow: hidden; padding: 0; margin: 0;">
|
<view class="form-row">
|
<view class="label">
|
<text class="required">*</text>物料码:
|
</view>
|
<view class="picker-wrap">
|
<view class="input-box">
|
<input
|
type="text"
|
v-model="scanBuffer"
|
placeholder="请扫码"
|
@input="handleMaterialScan"
|
ref="scanInput"
|
/>
|
</view>
|
</view>
|
</view>
|
</view>
|
|
<!-- 物料信息 -->
|
<view class="form-card material-card">
|
<view class="card-title">物料信息</view>
|
|
<!-- 多物料列表 -->
|
<view class="material-list" v-if="matList.length > 0">
|
<view class="material-item" v-for="(mat, index) in matList" :key="mat.id">
|
<view class="material-header">
|
<text class="material-title">物料 {{ index + 1 }}</text>
|
<view class="material-actions">
|
<view class="action-btn" @click="removeMaterial(index)">删除</view>
|
</view>
|
</view>
|
|
<view class="material-grid">
|
<view class="material-item">
|
<text class="material-label"><text class="required">*</text>位置:</text>
|
<input
|
class="material-input"
|
type="text"
|
v-model="mat.position"
|
placeholder="请选择位置"
|
placeholder-class="input-placeholder"
|
/>
|
</view>
|
<view class="material-item">
|
<text class="material-label"><text class="required">*</text>箱号:</text>
|
<input
|
class="material-input"
|
type="text"
|
v-model="mat.batch"
|
placeholder="请扫码或输入箱号"
|
placeholder-class="input-placeholder"
|
/>
|
</view>
|
<view class="material-item">
|
<text class="material-label"><text class="required">*</text>卷号:</text>
|
<input
|
class="material-input"
|
type="text"
|
v-model="mat.model"
|
placeholder="请扫码或输入卷号"
|
placeholder-class="input-placeholder"
|
/>
|
</view>
|
<view class="material-item">
|
<text class="material-label">规格:</text>
|
<input
|
class="material-input"
|
type="text"
|
v-model="mat.matnr"
|
placeholder="请输入规格"
|
placeholder-class="input-placeholder"
|
/>
|
</view>
|
<view class="material-item">
|
<text class="material-label">长度:</text>
|
<input
|
class="material-input"
|
type="number"
|
v-model="mat.rollExtent"
|
placeholder="请输入长度"
|
placeholder-class="input-placeholder"
|
/>
|
</view>
|
<view class="material-item">
|
<text class="material-label">净重:</text>
|
<input
|
class="material-input"
|
type="number"
|
v-model="mat.weight"
|
placeholder="请输入净重"
|
placeholder-class="input-placeholder"
|
/>
|
</view>
|
<view class="material-item">
|
<text class="material-label">毛重:</text>
|
<input
|
class="material-input"
|
type="number"
|
v-model="mat.roughWeight"
|
placeholder="请输入毛重"
|
placeholder-class="input-placeholder"
|
/>
|
</view>
|
<view class="material-item">
|
<text class="material-label">接头:</text>
|
<input
|
class="material-input"
|
type="number"
|
v-model="mat.joint"
|
placeholder="请输入接头数"
|
placeholder-class="input-placeholder"
|
/>
|
</view>
|
</view>
|
</view>
|
</view>
|
|
<!-- 空状态提示 -->
|
<view class="empty-state" v-else>
|
<view class="empty-icon">📦</view>
|
<text class="empty-text">暂无物料信息</text>
|
<text class="empty-tip">请扫描物料码添加物料</text>
|
</view>
|
|
<!-- 扫码按钮 -->
|
<view class="scan-btn" @click="focusScanInput">
|
<text class="scan-icon">+</text>
|
<text class="scan-text">扫码添加物料</text>
|
</view>
|
</view>
|
|
<!-- 操作按钮组 -->
|
<view class="btn-group">
|
<button class="operate-btn submit-btn" @click="submit">组托</button>
|
</view>
|
</view>
|
|
<!-- 扫码确认弹窗 -->
|
<view class="modal-mask" v-if="showScanModal" @click="closeModal">
|
<view class="modal-content" @click.stop>
|
<view class="modal-header">
|
<text class="modal-title">扫码确认</text>
|
</view>
|
<view class="modal-body">
|
<view class="scan-preview">
|
<text class="scan-label">扫描到物料:</text>
|
<text class="scan-code">{{ tempMaterial.model || '未知物料' }}</text>
|
</view>
|
|
<view class="preview-grid">
|
<view class="preview-item">
|
<text class="preview-label">箱号:</text>
|
<text class="preview-value">{{ tempMaterial.batch || '未识别' }}</text>
|
</view>
|
<view class="preview-item">
|
<text class="preview-label">卷号:</text>
|
<text class="preview-value">{{ tempMaterial.model || '未识别' }}</text>
|
</view>
|
<view class="preview-item">
|
<text class="preview-label">规格:</text>
|
<text class="preview-value">{{ tempMaterial.matnr || '未识别' }}</text>
|
</view>
|
<view class="preview-item">
|
<text class="preview-label">长度:</text>
|
<text class="preview-value">{{ tempMaterial.rollExtent || '未识别' }}</text>
|
</view>
|
<view class="preview-item">
|
<text class="preview-label">净重:</text>
|
<text class="preview-value">{{ tempMaterial.weight || '未识别' }}</text>
|
</view>
|
<view class="preview-item">
|
<text class="preview-label">毛重:</text>
|
<text class="preview-value">{{ tempMaterial.roughWeight || '未识别' }}</text>
|
</view>
|
<view class="preview-item">
|
<text class="preview-label">接头:</text>
|
<text class="preview-value">{{ tempMaterial.joint || '未识别' }}</text>
|
</view>
|
|
<view class="preview-item full-width">
|
<text class="preview-label">物料位置:</text>
|
<view class="position-selector" @click.stop="togglePositionPicker">
|
<view class="position-display">
|
<text v-if="positionIndex >= 0">{{ positionOptions[positionIndex].label }}</text>
|
<text v-else class="placeholder">请选择位置</text>
|
<text class="position-arrow">▼</text>
|
</view>
|
</view>
|
</view>
|
|
<!-- 新增:自定义选择器弹出层 -->
|
<view v-if="showPositionPicker" class="custom-picker-overlay" @click.stop="closePositionPicker">
|
<view class="custom-picker-content" @click.stop>
|
<view class="custom-picker-header">
|
<text class="custom-picker-title">选择物料位置</text>
|
<view class="custom-picker-close" @click="closePositionPicker">×</view>
|
</view>
|
<view class="custom-picker-list">
|
<view
|
v-for="(item, index) in positionOptions"
|
:key="index"
|
class="custom-picker-item"
|
:class="{'selected': positionIndex === index}"
|
@click="selectPosition(index)"
|
>
|
<text class="custom-picker-text">{{ item.label }}</text>
|
<text v-if="positionIndex === index" class="custom-picker-check">✓</text>
|
</view>
|
</view>
|
</view>
|
</view>
|
</view>
|
</view>
|
<view class="modal-footer">
|
<button class="modal-btn cancel" @click="cancelAddMaterial">取消</button>
|
<button class="modal-btn confirm" @click="confirmAddMaterial">确定添加</button>
|
</view>
|
</view>
|
</view>
|
</view>
|
</template>
|
|
<script>
|
export default {
|
onLoad(options) {
|
this.checkLoginStatus();
|
this.POSTinfo();
|
},
|
|
onShow() {
|
this.checkLoginStatus();
|
},
|
|
onHide() {
|
if (this.scanTimeout) {
|
clearTimeout(this.scanTimeout);
|
this.scanTimeout = null;
|
}
|
},
|
|
onReady() {
|
// 在页面准备就绪后初始化扫码监听
|
setTimeout(() => {
|
this.initScanListener();
|
}, 500);
|
},
|
|
data() {
|
return {
|
baseUrl: '',
|
token: '',
|
barcode: '',
|
boxType: '',
|
mode: [],
|
index_mode: 0,
|
|
// 扫码相关
|
scanBuffer: '',
|
scanTimeout: null,
|
|
// 物料列表
|
matList: [],
|
materialId: 1,
|
|
// 弹窗相关
|
showScanModal: false,
|
tempMaterial: {
|
model: '',
|
batch: '',
|
matnr: '',
|
rollExtent: '',
|
weight: '',
|
roughWeight: '',
|
joint: 0,
|
position: '1' // 新增:物料位置,默认值为"1"(左)
|
},
|
|
// 新增:物料位置下拉框相关数据
|
positionIndex: 0, // 默认选中第一个(左)
|
|
// 新增:控制自定义选择器显示
|
showPositionPicker: false,
|
positionOptions: [
|
{ label: '1', value: '1' },
|
{ label: '2', value: '2' }
|
]
|
}
|
},
|
|
methods: {
|
// 新增:切换位置选择器显示
|
togglePositionPicker() {
|
this.showPositionPicker = !this.showPositionPicker;
|
},
|
|
// 新增:关闭位置选择器
|
closePositionPicker() {
|
this.showPositionPicker = false;
|
},
|
|
// 新增:选择位置
|
selectPosition(index) {
|
this.positionIndex = index;
|
this.tempMaterial.position = this.positionOptions[index].value;
|
this.closePositionPicker();
|
},
|
|
// 初始化扫码监听
|
initScanListener() {
|
// 在uni-app中,可以通过ref获取DOM节点,但要注意平台差异
|
// 这里我们通过一个安全的方法来聚焦输入框
|
this.$nextTick(() => {
|
const input = this.$refs.scanInput;
|
if (input && typeof input.focus === 'function') {
|
input.focus();
|
}
|
});
|
},
|
|
// 聚焦扫码输入框
|
focusScanInput() {
|
// 使用uni-app的安全方法
|
this.$nextTick(() => {
|
const input = this.$refs.scanInput;
|
if (input) {
|
// 在uni-app中,input可能是一个组件实例
|
// 我们需要获取其DOM节点或使用平台特定的方法
|
// 这里我们尝试调用focus,如果不可用则跳过
|
try {
|
if (typeof input.focus === 'function') {
|
input.focus();
|
} else if (input.$el && typeof input.$el.focus === 'function') {
|
// 如果是Vue组件实例
|
input.$el.focus();
|
}
|
} catch (error) {
|
console.log('聚焦失败,但不影响功能:', error);
|
}
|
}
|
});
|
},
|
|
// 处理扫码输入
|
handleMaterialScan(e) {
|
const value = e.detail ? e.detail.value : e.target.value;
|
|
// 防抖处理
|
if (this.scanTimeout) {
|
clearTimeout(this.scanTimeout);
|
}
|
|
this.scanTimeout = setTimeout(() => {
|
if (value && value.trim()) {
|
this.parseBarcodeContent(value.trim());
|
this.showScanModal = true;
|
this.scanBuffer = ''; // 清空缓冲区
|
|
// 每次打开弹窗时重置位置选择为默认值
|
this.positionIndex = 0;
|
this.tempMaterial.position = '1';
|
}
|
}, 300);
|
},
|
|
// 解析条码内容
|
parseBarcodeContent(content) {
|
// const lines = content.split(/\\n/).filter(line => line.trim() !== '');
|
const lines = content.split(' ').filter(line => line.trim().length > 0);
|
|
// 清空临时数据
|
this.tempMaterial = {
|
model: '',
|
batch: '',
|
matnr: '',
|
rollExtent: '',
|
weight: '',
|
roughWeight: '',
|
joint: 0,
|
position: '1' // 重置位置为默认值
|
};
|
|
// 使用正则表达式提取键值对[6,7](@ref)
|
const extractKeyValue = (line) => {
|
const match = line.match(/([^:]+):(.+)/);
|
if (match && match.length === 3) {
|
return {
|
key: match[1].trim(),
|
value: match[2].trim()
|
};
|
}
|
return null;
|
};
|
|
// 提取数字(包括小数)[6,7](@ref)
|
const extractNumber = (str) => {
|
const match = str.match(/[\d.]+/);
|
return match ? match[0] : '';
|
};
|
|
// 遍历每一行,解析键值对
|
lines.forEach(line => {
|
const keyValue = extractKeyValue(line);
|
if (keyValue) {
|
const { key, value } = keyValue;
|
|
switch (key) {
|
case '卷号':
|
this.tempMaterial.model = value;
|
break;
|
case '箱号':
|
this.tempMaterial.batch = value;
|
break;
|
case '规格':
|
this.tempMaterial.matnr = value;
|
break;
|
case '长度':
|
this.tempMaterial.rollExtent = extractNumber(value);
|
break;
|
case '净重':
|
this.tempMaterial.weight = extractNumber(value);
|
break;
|
case '毛重':
|
this.tempMaterial.roughWeight = extractNumber(value);
|
break;
|
case '接头':
|
this.tempMaterial.joint = extractNumber(value) || 0;
|
break;
|
default:
|
// 可以处理未知键或忽略
|
break;
|
}
|
}
|
});
|
},
|
|
// 确认添加物料
|
confirmAddMaterial() {
|
this.closePositionPicker();
|
if (!this.tempMaterial.model) {
|
uni.showToast({
|
title: '卷号不能为空',
|
icon: 'none'
|
});
|
return;
|
}
|
|
// 检查是否已存在相同物料
|
const exists = this.matList.some(item =>
|
item.model === this.tempMaterial.model &&
|
item.batch === this.tempMaterial.batch
|
);
|
|
if (exists) {
|
uni.showToast({
|
title: '该物料已存在',
|
icon: 'none'
|
});
|
this.closeModal();
|
return;
|
};
|
|
// 添加到物料列表
|
const newMaterial = {
|
id: this.materialId++,
|
...this.tempMaterial,
|
position: (this.matList.length + 1).toString(),
|
cutting: 2,
|
qualified: 0
|
};
|
|
this.matList.push(newMaterial);
|
|
uni.showToast({
|
title: '物料添加成功',
|
icon: 'success'
|
});
|
|
this.closeModal();
|
},
|
|
// 取消添加
|
cancelAddMaterial() {
|
this.closeModal();
|
},
|
|
// 关闭弹窗
|
closeModal() {
|
this.showPositionPicker = false;
|
this.showScanModal = false;
|
this.tempMaterial = {
|
model: '',
|
batch: '',
|
matnr: '',
|
rollExtent: '',
|
weight: '',
|
roughWeight: '',
|
joint: 0,
|
position: '1' // 重置位置
|
};
|
|
// 重置位置选择
|
this.positionIndex = 0;
|
|
// 重新聚焦到扫码输入框
|
setTimeout(() => {
|
this.focusScanInput();
|
}, 100);
|
},
|
|
// 删除物料
|
removeMaterial(index) {
|
uni.showModal({
|
title: '确认删除',
|
content: '确定要删除这个物料吗?',
|
success: (res) => {
|
if (res.confirm) {
|
this.matList.splice(index, 1);
|
uni.showToast({
|
title: '删除成功',
|
icon: 'success'
|
});
|
}
|
}
|
});
|
},
|
|
// 检查登录状态
|
checkLoginStatus() {
|
this.token = uni.getStorageSync('token');
|
this.baseUrl = uni.getStorageSync('baseUrl');
|
|
if (!this.token || !this.baseUrl) {
|
uni.showModal({
|
title: '提示',
|
content: '请先登录',
|
showCancel: false,
|
success: (res) => {
|
if (res.confirm) {
|
uni.navigateTo({
|
url: '/pages/login/login'
|
});
|
}
|
}
|
});
|
return false;
|
}
|
return true;
|
},
|
|
// 获取箱型数据
|
POSTinfo() {
|
if (!this.checkLoginStatus()) return;
|
|
uni.showLoading({
|
title: '加载中...'
|
});
|
|
uni.request({
|
url: this.baseUrl + '/mobile/box/type/complete/auth/v2',
|
method: 'POST',
|
header: {
|
'Content-Type': 'application/json',
|
'Authorization': 'Bearer ' + this.token
|
},
|
success: (res) => {
|
uni.hideLoading();
|
|
if (res.data && res.data.code === 200 && Array.isArray(res.data.data)) {
|
this.mode = res.data.data
|
.map(item => item.boxSpecs || item.boxType || item.typeName || item.name || '')
|
.filter(item => item && item.trim() !== '');
|
if (this.mode.length === 0) {
|
uni.showToast({
|
title: '无可用箱型',
|
icon: 'none'
|
});
|
}
|
} else {
|
uni.showToast({
|
title: res.data?.message || '获取箱型失败',
|
icon: 'none'
|
});
|
}
|
},
|
fail: (err) => {
|
uni.hideLoading();
|
console.error('获取箱型失败:', err);
|
uni.showToast({
|
title: '网络错误',
|
icon: 'none'
|
});
|
}
|
});
|
},
|
|
modePickerChange(e) {
|
this.index_mode = e.detail.value;
|
this.boxType = this.mode[this.index_mode];
|
},
|
|
// 提交数据
|
submit() {
|
if (!this.checkLoginStatus()) return;
|
|
// 验证必填项
|
if (!this.barcode) {
|
uni.showToast({title: '请扫描托盘编码', icon: 'none'});
|
return;
|
}
|
|
this.boxType = 999;
|
if (!this.boxType) {
|
uni.showToast({title: '请选择箱型', icon: 'none'});
|
return;
|
}
|
|
if (this.matList.length === 0) {
|
uni.showToast({title: '请至少添加一个物料', icon: 'none'});
|
return;
|
}
|
|
// 验证每个物料的必填字段
|
for (let i = 0; i < this.matList.length; i++) {
|
const mat = this.matList[i];
|
if (!mat.model) {
|
uni.showToast({title: `物料${i+1}卷号不能为空`, icon: 'none'});
|
return;
|
}
|
if (!mat.batch) {
|
uni.showToast({title: `物料${i+1}箱号不能为空`, icon: 'none'});
|
return;
|
}
|
}
|
|
// 准备提交数据
|
const submitData = {
|
barcode: this.barcode,
|
boxType: this.boxType,
|
matList: this.matList.map(mat => ({
|
...mat,
|
weight: mat.weight ? Number(mat.weight) : null,
|
roughWeight: mat.roughWeight ? Number(mat.roughWeight) : null,
|
rollExtent: mat.rollExtent ? Number(mat.rollExtent) : null,
|
joint: mat.joint ? Number(mat.joint) : 0,
|
position: mat.position // 包含位置信息
|
}))
|
};
|
|
console.log('提交数据:', submitData);
|
|
// 发送请求
|
uni.showLoading({
|
title: '提交中...',
|
mask: true
|
});
|
|
uni.request({
|
url: this.baseUrl + '/mobile/truss/comd/auth/v2',
|
method: 'POST',
|
header: {
|
'Content-Type': 'application/json',
|
'Authorization': 'Bearer ' + this.token
|
},
|
data: submitData,
|
success: (res) => {
|
uni.hideLoading();
|
|
if (res.data.code === 200) {
|
uni.showToast({
|
title: '提交成功',
|
icon: 'success',
|
duration: 2000
|
});
|
|
// 清空表单
|
setTimeout(() => {
|
this.resetForm();
|
}, 1500);
|
} else {
|
uni.showToast({
|
title: res.data.msg || '提交失败',
|
icon: 'none'
|
});
|
}
|
},
|
fail: (err) => {
|
uni.hideLoading();
|
console.error('提交失败:', err);
|
uni.showToast({
|
title: '网络错误',
|
icon: 'none'
|
});
|
}
|
});
|
},
|
|
// 重置表单
|
resetForm() {
|
this.barcode = '';
|
this.boxType = '';
|
this.index_mode = 0;
|
this.matList = [];
|
this.materialId = 1;
|
}
|
}
|
}
|
</script>
|
|
<style scoped>
|
|
/* 物料位置选择器样式 */
|
.full-width {
|
grid-column: 1 / -1; /* 占满整行 */
|
margin-top: 8rpx;
|
position: relative;
|
z-index: 100; /* 确保在弹窗内部层级正常 */
|
}
|
|
.position-selector {
|
width: 200rpx;
|
display: flex;
|
justify-content: flex-end;
|
}
|
|
.position-picker {
|
width: 200rpx;
|
}
|
|
.position-display {
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
padding: 8rpx 16rpx;
|
border: 1rpx solid #e5e7eb;
|
border-radius: 6rpx;
|
background-color: #ffffff;
|
color: #333;
|
font-size: 28rpx;
|
min-height: 40rpx;
|
width: 100%;
|
box-sizing: border-box;
|
}
|
|
.placeholder {
|
color: #999;
|
}
|
|
.position-arrow {
|
font-size: 20rpx;
|
color: #666;
|
margin-left: 8rpx;
|
}
|
/* 全局样式 - 保持原有风格 */
|
.sockpage {
|
background-color: #f5f7fa;
|
padding: 20rpx;
|
min-height: 100vh;
|
}
|
|
.column {
|
display: flex;
|
flex-direction: column;
|
gap: 20rpx;
|
}
|
|
.form-card {
|
background: #ffffff;
|
border-radius: 8rpx;
|
padding: 20rpx;
|
box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.1);
|
}
|
|
.form-row {
|
display: flex;
|
align-items: center;
|
gap: 20rpx;
|
}
|
|
.label {
|
font-size: 28rpx;
|
color: #333;
|
font-weight: 500;
|
min-width: 140rpx;
|
}
|
|
.required {
|
color: #e64340;
|
margin-right: 4rpx;
|
}
|
|
.picker-wrap {
|
flex: 1;
|
}
|
|
.input-box {
|
border: 1rpx solid #e5e7eb;
|
border-radius: 6rpx;
|
padding: 16rpx 20rpx;
|
background: #fff;
|
}
|
|
.input-placeholder {
|
color: #999;
|
font-size: 28rpx;
|
}
|
|
.input-value {
|
color: #333;
|
font-size: 28rpx;
|
}
|
|
/* 物料信息卡片 */
|
.material-card {
|
padding: 0;
|
}
|
|
.card-title {
|
font-size: 30rpx;
|
font-weight: 500;
|
color: #333;
|
padding: 20rpx 20rpx 16rpx;
|
border-bottom: 1rpx solid #f0f0f0;
|
}
|
|
/* 物料列表 */
|
.material-list {
|
padding: 0 20rpx;
|
}
|
|
.material-item {
|
margin-bottom: 20rpx;
|
}
|
|
.material-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
margin-bottom: 16rpx;
|
padding-bottom: 12rpx;
|
border-bottom: 1rpx solid #f0f0f0;
|
}
|
|
.material-title {
|
font-size: 28rpx;
|
font-weight: 500;
|
color: #333;
|
}
|
|
.material-actions {
|
display: flex;
|
gap: 20rpx;
|
}
|
|
.action-btn {
|
font-size: 24rpx;
|
color: #e64340;
|
padding: 6rpx 12rpx;
|
border-radius: 4rpx;
|
background: #fff0f0;
|
}
|
|
/* 物料网格 */
|
.material-grid {
|
display: grid;
|
grid-template-columns: repeat(2, 1fr);
|
gap: 16rpx;
|
}
|
|
.material-item {
|
display: flex;
|
flex-direction: column;
|
gap: 8rpx;
|
}
|
|
.material-label {
|
font-size: 26rpx;
|
color: #666;
|
}
|
|
.material-input {
|
font-size: 28rpx;
|
color: #333;
|
padding: 12rpx;
|
border: 1rpx solid #e5e7eb;
|
border-radius: 6rpx;
|
background-color: #ffffff;
|
}
|
|
/* 空状态 */
|
.empty-state {
|
text-align: center;
|
padding: 40rpx 20rpx;
|
}
|
|
.empty-icon {
|
font-size: 60rpx;
|
display: block;
|
margin-bottom: 20rpx;
|
opacity: 0.5;
|
}
|
|
.empty-text {
|
display: block;
|
font-size: 28rpx;
|
color: #999;
|
margin-bottom: 10rpx;
|
}
|
|
.empty-tip {
|
display: block;
|
font-size: 24rpx;
|
color: #ccc;
|
}
|
|
/* 扫码按钮 */
|
.scan-btn {
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
gap: 10rpx;
|
padding: 20rpx;
|
margin: 20rpx 20rpx 20rpx;
|
background: #f0f7ff;
|
border: 1rpx dashed #1989fa;
|
border-radius: 8rpx;
|
color: #1989fa;
|
font-size: 28rpx;
|
}
|
|
.scan-icon {
|
font-size: 36rpx;
|
font-weight: bold;
|
}
|
|
/* 按钮组 */
|
.btn-group {
|
margin-top: 20rpx;
|
padding: 8rpx 0;
|
text-align: center;
|
}
|
|
.operate-btn {
|
width: 200rpx;
|
height: 80rpx;
|
line-height: 80rpx;
|
font-size: 30rpx;
|
font-weight: 500;
|
border-radius: 8rpx;
|
border: none;
|
background: #333;
|
color: #fff;
|
}
|
|
/* 弹窗样式 */
|
.modal-mask {
|
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: 1000;
|
}
|
|
.modal-content {
|
background: #fff;
|
border-radius: 12rpx;
|
width: 600rpx;
|
max-width: 90%;
|
overflow: hidden;
|
}
|
|
.modal-header {
|
padding: 30rpx 30rpx 20rpx;
|
border-bottom: 1rpx solid #f0f0f0;
|
}
|
|
.modal-title {
|
font-size: 32rpx;
|
font-weight: 500;
|
color: #333;
|
}
|
|
.modal-body {
|
padding: 30rpx;
|
}
|
|
.scan-preview {
|
margin-bottom: 20rpx;
|
padding-bottom: 20rpx;
|
border-bottom: 1rpx solid #f0f0f0;
|
}
|
|
.scan-label {
|
font-size: 28rpx;
|
color: #666;
|
display: block;
|
margin-bottom: 10rpx;
|
}
|
|
.scan-code {
|
font-size: 32rpx;
|
color: #333;
|
font-weight: bold;
|
word-break: break-all;
|
}
|
|
.preview-grid {
|
display: grid;
|
grid-template-columns: repeat(2, 1fr);
|
gap: 15rpx;
|
}
|
|
.preview-item {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
}
|
|
.preview-label {
|
font-size: 28rpx;
|
color: #666;
|
}
|
|
.preview-value {
|
font-size: 28rpx;
|
color: #333;
|
font-weight: 500;
|
}
|
|
.modal-footer {
|
display: flex;
|
border-top: 1rpx solid #f0f0f0;
|
}
|
|
.modal-btn {
|
flex: 1;
|
height: 90rpx;
|
line-height: 90rpx;
|
font-size: 30rpx;
|
border: none;
|
background: transparent;
|
border-radius: 0;
|
}
|
|
.modal-btn.cancel {
|
color: #999;
|
border-right: 1rpx solid #f0f0f0;
|
}
|
|
.modal-btn.confirm {
|
color: #1989fa;
|
font-weight: 500;
|
}
|
|
/* 自定义选择器样式 */
|
.custom-picker-overlay {
|
position: fixed;
|
top: 0;
|
left: 0;
|
right: 0;
|
bottom: 0;
|
background-color: rgba(0, 0, 0, 0.5);
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
z-index: 9999; /* 确保在最上层 */
|
}
|
|
.custom-picker-content {
|
background-color: #ffffff;
|
border-radius: 12rpx;
|
width: 600rpx;
|
max-width: 80%;
|
max-height: 70vh;
|
overflow: hidden;
|
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.15);
|
animation: fadeIn 0.3s ease;
|
}
|
|
@keyframes fadeIn {
|
from {
|
opacity: 0;
|
transform: translateY(20rpx);
|
}
|
to {
|
opacity: 1;
|
transform: translateY(0);
|
}
|
}
|
|
.custom-picker-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
padding: 30rpx;
|
border-bottom: 1rpx solid #f0f0f0;
|
}
|
|
.custom-picker-title {
|
font-size: 32rpx;
|
font-weight: 500;
|
color: #333;
|
}
|
|
.custom-picker-close {
|
font-size: 40rpx;
|
color: #999;
|
line-height: 1;
|
padding: 0 10rpx;
|
cursor: pointer;
|
}
|
|
.custom-picker-list {
|
max-height: 50vh;
|
overflow-y: auto;
|
padding: 0;
|
}
|
|
.custom-picker-item {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
padding: 25rpx 30rpx;
|
border-bottom: 1rpx solid #f5f5f5;
|
cursor: pointer;
|
transition: background-color 0.2s;
|
}
|
|
.custom-picker-item:last-child {
|
border-bottom: none;
|
}
|
|
.custom-picker-item:hover {
|
background-color: #f8f9fa;
|
}
|
|
.custom-picker-item.selected {
|
background-color: #f0f7ff;
|
color: #1989fa;
|
}
|
|
.custom-picker-text {
|
font-size: 30rpx;
|
}
|
|
.custom-picker-check {
|
font-size: 28rpx;
|
color: #1989fa;
|
font-weight: bold;
|
}
|
|
/* 弹窗样式调整,确保层级关系 */
|
.modal-mask {
|
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: 1000; /* 弹窗基础层级 */
|
}
|
|
.modal-content {
|
position: relative; /* 确保子元素相对定位 */
|
z-index: 1001; /* 比蒙版高一级 */
|
background: #fff;
|
border-radius: 12rpx;
|
width: 600rpx;
|
max-width: 90%;
|
overflow: visible; /* 改为 visible 允许选择器弹出 */
|
}
|
|
/* 响应式适配 */
|
@media (max-width: 750rpx) {
|
.material-grid {
|
grid-template-columns: 1fr;
|
}
|
|
.preview-grid {
|
grid-template-columns: 1fr;
|
}
|
|
.modal-content {
|
width: 90%;
|
}
|
.custom-picker-content {
|
width: 90%;
|
max-width: 90%;
|
}
|
|
.custom-picker-item {
|
padding: 20rpx 25rpx;
|
}
|
}
|
</style>
|