|
|
@@ -7,7 +7,7 @@
|
|
|
<!-- 顶部标题区域 -->
|
|
|
<div class="header-section">
|
|
|
<button class="logout-btn" @click="goBack">
|
|
|
- <i class="fas fa-home" />
|
|
|
+ <i class="fas fa-arrow-left" />
|
|
|
<span>返回领料</span>
|
|
|
</button>
|
|
|
<h1 class="page-title">常用领料</h1>
|
|
|
@@ -122,6 +122,53 @@
|
|
|
<i class="fas fa-map-marker-alt location-icon" />
|
|
|
<span class="info-value">{{ item.inventoryActulPosition || item.inventoryPosition || '-' }} / {{ item.inventoryWarehouse || '-' }}</span>
|
|
|
</div>
|
|
|
+ <!-- 配送类型徽章 -->
|
|
|
+ <div class="info-row delivery-type-row">
|
|
|
+ <span class="delivery-type-badge" :class="getDeliveryTypeBadgeClass(item.deliveryType)">
|
|
|
+ {{ item.deliveryType || '未指定' }}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 配送选择区域(固定高度,始终存在) -->
|
|
|
+ <div class="card-delivery-section" @click.stop>
|
|
|
+ <!-- 选中时显示配送选择 -->
|
|
|
+ <template v-if="selectedIds.includes(item.id)">
|
|
|
+ <div class="delivery-row">
|
|
|
+ <span class="delivery-label">配送:</span>
|
|
|
+ <div class="delivery-method-buttons">
|
|
|
+ <button
|
|
|
+ :class="['delivery-btn', { 'active': item.deliveryMethod === 'AGV_Delivery', 'disabled': item.deliveryType === '人工配送' }]"
|
|
|
+ :disabled="item.deliveryType === '人工配送'" @click="changeDeliveryMethod(item, 'AGV_Delivery')"
|
|
|
+ >
|
|
|
+ <i class="fas fa-robot" /> AGV
|
|
|
+ </button>
|
|
|
+ <button
|
|
|
+ :class="['delivery-btn', { 'active': item.deliveryMethod === 'Manual_Delivery', 'disabled': item.deliveryType === '强制AGV配送' }]"
|
|
|
+ :disabled="item.deliveryType === '强制AGV配送'"
|
|
|
+ @click="changeDeliveryMethod(item, 'Manual_Delivery')"
|
|
|
+ >
|
|
|
+ <i class="fas fa-user" /> 人工
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <!-- AGV配送位置选择 -->
|
|
|
+ <div class="delivery-location-row">
|
|
|
+ <span class="delivery-label">位置:</span>
|
|
|
+ <v-select
|
|
|
+ v-if="item.deliveryMethod === 'AGV_Delivery'" v-model="item.selectedLocation"
|
|
|
+ :options="locator" :clearable="false" class="location-select dark-select" :append-to-body="true"
|
|
|
+ :calculate-position="withPopper"
|
|
|
+ />
|
|
|
+ <span v-else style="font-size: 16px;">人工配送</span>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <!-- 未选中时显示占位 -->
|
|
|
+ <template v-else>
|
|
|
+ <div class="delivery-placeholder">
|
|
|
+ <span>点击选择后设置配送方式</span>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
</div>
|
|
|
|
|
|
<!-- 选中状态指示 -->
|
|
|
@@ -144,13 +191,36 @@
|
|
|
|
|
|
<!-- 底部操作按钮 -->
|
|
|
<div class="bottom-actions">
|
|
|
- <button
|
|
|
- class="submit-btn"
|
|
|
- :disabled="selectedIds.length === 0"
|
|
|
- @click="submitStock"
|
|
|
- >
|
|
|
+ <button class="submit-btn" :disabled="selectedIds.length === 0" @click="submitStock">
|
|
|
加入领料车
|
|
|
</button>
|
|
|
+ <button class="pick-btn" :disabled="selectedIds.length === 0" @click="handleComplete">
|
|
|
+ 领料
|
|
|
+ <!-- ({{ selectedIds.length }}) -->
|
|
|
+ <span v-if="selectedIds && selectedIds.length > 0">({{ selectedIds.length }})</span>
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 拣货完成确认弹窗 - 科技感风格 -->
|
|
|
+ <div v-if="completeModalVisible" class="tech-modal-overlay" @click.self="handleCompleteCancel">
|
|
|
+ <div class="tech-modal success-modal">
|
|
|
+ <div class="modal-content-row">
|
|
|
+ <div class="modal-text">
|
|
|
+ <h3>领料完成</h3>
|
|
|
+ <p>领料申请已完成,配送任务已创建!<br />请确认是否返回主页?</p>
|
|
|
+ </div>
|
|
|
+ <div class="modal-icon">
|
|
|
+ <div class="icon-box success-box">
|
|
|
+ <i class="fas fa-truck-loading" />
|
|
|
+ <i class="fas fa-check check-icon" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="modal-footer">
|
|
|
+ <button class="modal-btn cancel-btn" @click="handleCompleteCancel">取消</button>
|
|
|
+ <button class="modal-btn confirm-btn" @click="handleCompleteConfirm">确认</button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
|
|
|
<!-- Loading -->
|
|
|
@@ -175,8 +245,9 @@ import 'vue-select/dist/vue-select.css';
|
|
|
// 图片资源
|
|
|
import bgImg from '../assets/images/bj.png';
|
|
|
|
|
|
-import { getWarehouseList } from '../api/stock.js';
|
|
|
-import { queryCommonUse, createStockOutPrepareLine, queryPickingCarNumber } from '../api/stockOut.js';
|
|
|
+import { getWarehouseList, queryFeedAreaStatus } from '../api/stock.js';
|
|
|
+import { queryCommonUse, createStockOutPrepareLine, queryPickingCarNumber, generatePickPaper } from '../api/stockOut.js';
|
|
|
+import { gateController } from '../hardware/GateOperate.js';
|
|
|
|
|
|
const router = useRouter();
|
|
|
|
|
|
@@ -191,11 +262,18 @@ const count = ref(0);
|
|
|
const warehouseList = ref([]);
|
|
|
const stockRequisitionList = ref([]);
|
|
|
const selectedIds = ref([]);
|
|
|
+const selectedRows = ref([]);
|
|
|
|
|
|
const loading = ref(false);
|
|
|
const loadingMore = ref(false);
|
|
|
const noMoreData = ref(false);
|
|
|
|
|
|
+// 弹窗控制
|
|
|
+const completeModalVisible = ref(false);
|
|
|
+
|
|
|
+// 可配送位置
|
|
|
+const locator = ref([]);
|
|
|
+
|
|
|
const inventoryTypeList = ref([
|
|
|
{ value: 'Clamp', label: '工装' },
|
|
|
{ value: 'Instrument', label: '设备' },
|
|
|
@@ -207,6 +285,45 @@ const pageSize = 20;
|
|
|
const currentStart = ref(0);
|
|
|
const total = ref(0);
|
|
|
|
|
|
+// 根据 deliveryType 初始化配送方式
|
|
|
+const initDeliveryMethod = item => {
|
|
|
+ if (item.deliveryType === '人工配送') {
|
|
|
+ // 人工配送:只能人工,不可切换
|
|
|
+ item.deliveryMethod = 'Manual_Delivery';
|
|
|
+ item.selectedLocation = '';
|
|
|
+ } else if (item.deliveryType === '强制AGV配送') {
|
|
|
+ // 强制AGV配送:只能AGV,不可切换为人工
|
|
|
+ item.deliveryMethod = 'AGV_Delivery';
|
|
|
+ if (!item.selectedLocation) {
|
|
|
+ item.selectedLocation = '';
|
|
|
+ }
|
|
|
+ } else if (item.deliveryType === '可选AGV配送') {
|
|
|
+ // 可选AGV配送:默认人工,可切换为AGV
|
|
|
+ item.deliveryMethod = item.deliveryMethod || 'Manual_Delivery';
|
|
|
+ item.selectedLocation = item.selectedLocation || '';
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 获取配送类型徽章样式
|
|
|
+const getDeliveryTypeBadgeClass = deliveryType => {
|
|
|
+ const classMap = {
|
|
|
+ '人工配送': 'badge-manual',
|
|
|
+ '强制AGV配送': 'badge-agv-force',
|
|
|
+ '可选AGV配送': 'badge-agv-optional',
|
|
|
+ };
|
|
|
+ return classMap[deliveryType] || '';
|
|
|
+};
|
|
|
+
|
|
|
+// 配送方式变更处理
|
|
|
+const changeDeliveryMethod = (item, method) => {
|
|
|
+ item.deliveryMethod = method;
|
|
|
+ // 当选择人工配送时,清空配送位置
|
|
|
+ if (method === 'Manual_Delivery') {
|
|
|
+ item.selectedLocation = '';
|
|
|
+ }
|
|
|
+ console.log('配送方式变更:', item.inventoryName, item.deliveryMethod);
|
|
|
+};
|
|
|
+
|
|
|
// 打开领料车
|
|
|
const openStockOutCar = () => {
|
|
|
router.push('/stock-picking-car?isRegular=true');
|
|
|
@@ -223,8 +340,16 @@ const toggleSelect = id => {
|
|
|
const index = selectedIds.value.indexOf(id);
|
|
|
if (index > -1) {
|
|
|
selectedIds.value.splice(index, 1);
|
|
|
+ selectedRows.value = selectedRows.value.filter(item => item.id !== id);
|
|
|
} else {
|
|
|
selectedIds.value.push(id);
|
|
|
+ // 添加到 selectedRows 并初始化配送字段
|
|
|
+ const item = stockRequisitionList.value.find(item => item.id === id);
|
|
|
+ if (item) {
|
|
|
+ // 初始化配送字段
|
|
|
+ initDeliveryMethod(item);
|
|
|
+ selectedRows.value.push(item);
|
|
|
+ }
|
|
|
}
|
|
|
};
|
|
|
|
|
|
@@ -234,11 +359,14 @@ const toggleSelectAll = checked => {
|
|
|
stockRequisitionList.value.forEach(item => {
|
|
|
if (!selectedIds.value.includes(item.id)) {
|
|
|
selectedIds.value.push(item.id);
|
|
|
+ initDeliveryMethod(item);
|
|
|
+ selectedRows.value.push(item);
|
|
|
}
|
|
|
});
|
|
|
} else {
|
|
|
const currentListIds = stockRequisitionList.value.map(item => item.id);
|
|
|
selectedIds.value = selectedIds.value.filter(id => !currentListIds.includes(id));
|
|
|
+ selectedRows.value = selectedRows.value.filter(item => !currentListIds.includes(item.id));
|
|
|
}
|
|
|
};
|
|
|
|
|
|
@@ -300,7 +428,36 @@ const loadMore = async () => {
|
|
|
const res = await queryCommonUse(params);
|
|
|
if (res.errorCode == 0) {
|
|
|
if (res.datas && res.datas.length > 0) {
|
|
|
- stockRequisitionList.value = [...stockRequisitionList.value, ...res.datas];
|
|
|
+ // 处理新加载的数据,保留已选中物料的配送方式设置
|
|
|
+ const newData = res.datas.map(item => {
|
|
|
+ const selectedItem = selectedRows.value.find(selected => selected.id === item.id);
|
|
|
+
|
|
|
+ if (selectedItem) {
|
|
|
+ // 如果已选中,保留其配送方式和位置设置
|
|
|
+ const updatedItem = {
|
|
|
+ ...item,
|
|
|
+ deliveryMethod: selectedItem.deliveryMethod,
|
|
|
+ selectedLocation: selectedItem.selectedLocation,
|
|
|
+ };
|
|
|
+
|
|
|
+ // 更新 selectedRows 中对应项的引用
|
|
|
+ const selectedIndex = selectedRows.value.findIndex(selected => selected.id === item.id);
|
|
|
+ if (selectedIndex !== -1) {
|
|
|
+ selectedRows.value[selectedIndex] = updatedItem;
|
|
|
+ }
|
|
|
+
|
|
|
+ return updatedItem;
|
|
|
+ } else {
|
|
|
+ // 未选中,初始化为空
|
|
|
+ return {
|
|
|
+ ...item,
|
|
|
+ deliveryMethod: '',
|
|
|
+ selectedLocation: '',
|
|
|
+ };
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ stockRequisitionList.value = [...stockRequisitionList.value, ...newData];
|
|
|
currentStart.value += res.datas.length;
|
|
|
total.value = res.total;
|
|
|
|
|
|
@@ -349,7 +506,35 @@ const getStockRequisitionList = async () => {
|
|
|
const res = await queryCommonUse(params);
|
|
|
if (res.errorCode == 0) {
|
|
|
if (res.datas && res.datas.length > 0) {
|
|
|
- stockRequisitionList.value = res.datas;
|
|
|
+ // 保留已选中物料的配送方式设置
|
|
|
+ stockRequisitionList.value = res.datas.map(item => {
|
|
|
+ // 查找该物料是否在已选中列表中
|
|
|
+ const selectedItem = selectedRows.value.find(selected => selected.id === item.id);
|
|
|
+
|
|
|
+ if (selectedItem) {
|
|
|
+ // 如果已选中,保留其配送方式和位置设置,并更新 selectedRows 中的引用
|
|
|
+ const updatedItem = {
|
|
|
+ ...item,
|
|
|
+ deliveryMethod: selectedItem.deliveryMethod,
|
|
|
+ selectedLocation: selectedItem.selectedLocation,
|
|
|
+ };
|
|
|
+
|
|
|
+ // 更新 selectedRows 中对应项的引用
|
|
|
+ const selectedIndex = selectedRows.value.findIndex(selected => selected.id === item.id);
|
|
|
+ if (selectedIndex !== -1) {
|
|
|
+ selectedRows.value[selectedIndex] = updatedItem;
|
|
|
+ }
|
|
|
+
|
|
|
+ return updatedItem;
|
|
|
+ } else {
|
|
|
+ // 未选中,初始化为空
|
|
|
+ return {
|
|
|
+ ...item,
|
|
|
+ deliveryMethod: '',
|
|
|
+ selectedLocation: '',
|
|
|
+ };
|
|
|
+ }
|
|
|
+ });
|
|
|
currentStart.value = res.datas.length;
|
|
|
total.value = res.total;
|
|
|
|
|
|
@@ -435,6 +620,7 @@ const submitStock = async () => {
|
|
|
const res = await createStockOutPrepareLine(params);
|
|
|
if (res.errorCode == 0) {
|
|
|
selectedIds.value = [];
|
|
|
+ selectedRows.value = [];
|
|
|
showNotify({ type: 'success', message: '已添加到领料车' });
|
|
|
// 先等待提交完成,再刷新列表
|
|
|
await getDatas();
|
|
|
@@ -448,6 +634,62 @@ const submitStock = async () => {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+// 领料申请,直接验证并提交
|
|
|
+const handleComplete = async () => {
|
|
|
+ if (selectedIds.value.length === 0) {
|
|
|
+ showNotify({ type: 'danger', message: '请至少选择一个物料' });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证选择了 AGV 配送的物料是否都选择了配送位置
|
|
|
+ const agvItems = selectedRows.value.filter(item => item.deliveryMethod === 'AGV_Delivery');
|
|
|
+ const hasEmptyLocation = agvItems.some(item => !item.selectedLocation);
|
|
|
+
|
|
|
+ if (hasEmptyLocation) {
|
|
|
+ showNotify({ type: 'danger', message: '请为所有 AGV 配送的物料选择配送位置' });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const params = [];
|
|
|
+ selectedRows.value.forEach(item => {
|
|
|
+ params.push({
|
|
|
+ inventoryId: item.id,
|
|
|
+ deliveryMethod: item.deliveryMethod,
|
|
|
+ positionEndNo: item.selectedLocation.value,
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ console.log('提交参数:', params);
|
|
|
+ const res = await generatePickPaper(params);
|
|
|
+ if (res.errorCode == 0) {
|
|
|
+ showNotify({ type: 'success', message: '领料申请成功' });
|
|
|
+ selectedIds.value = [];
|
|
|
+ selectedRows.value = [];
|
|
|
+ // 显示完成确认弹窗
|
|
|
+ gateController('SHOTOPEN');
|
|
|
+ router.push('/');
|
|
|
+ } else {
|
|
|
+ showNotify({ type: 'danger', message: res.errorMessage });
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 处理完成确认
|
|
|
+const handleCompleteConfirm = () => {
|
|
|
+ // 调用开门操作
|
|
|
+ gateController('SHOTOPEN');
|
|
|
+ completeModalVisible.value = false;
|
|
|
+ router.push('/home');
|
|
|
+};
|
|
|
+
|
|
|
+// 处理完成取消
|
|
|
+const handleCompleteCancel = () => {
|
|
|
+ completeModalVisible.value = false;
|
|
|
+ // 清理选择状态并刷新列表
|
|
|
+ selectedIds.value = [];
|
|
|
+ selectedRows.value = [];
|
|
|
+ getDatas();
|
|
|
+};
|
|
|
+
|
|
|
/**
|
|
|
* 查询领料车中的数量
|
|
|
*/
|
|
|
@@ -463,16 +705,43 @@ const queryPickingCarCount = async () => {
|
|
|
} else {
|
|
|
showNotify({ type: 'danger', message: res.errorMessage });
|
|
|
}
|
|
|
-
|
|
|
} catch (error) {
|
|
|
console.error('查询领料车数量失败:', error);
|
|
|
showNotify({ type: 'danger', message: '查询领料车数量失败' });
|
|
|
}
|
|
|
};
|
|
|
+
|
|
|
+// 获取送料区货位
|
|
|
+const getFeedAreaLocator = async () => {
|
|
|
+ try {
|
|
|
+ const res = await queryFeedAreaStatus();
|
|
|
+
|
|
|
+ if (res.errorCode === 0) {
|
|
|
+ if (res.datas && res.datas.length > 0) {
|
|
|
+ locator.value = res.datas.map(item => {
|
|
|
+ return {
|
|
|
+ label: item.positionName,
|
|
|
+ value: item.positionNo,
|
|
|
+ };
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ locator.value = [];
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ showNotify({ type: 'danger', message: res.errorMessage });
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('获取送料区货位API调用失败:', error);
|
|
|
+ showNotify({ type: 'danger', message: '获取送料区货位API调用失败' });
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 页面加载时初始化数据
|
|
|
onMounted(() => {
|
|
|
getDatas();
|
|
|
getWarehouses();
|
|
|
queryPickingCarCount();
|
|
|
+ getFeedAreaLocator();
|
|
|
});
|
|
|
</script>
|
|
|
|
|
|
@@ -874,12 +1143,14 @@ onMounted(() => {
|
|
|
background: rgba(4, 28, 61, 0.95);
|
|
|
z-index: 20;
|
|
|
flex-shrink: 0;
|
|
|
+ display: flex;
|
|
|
+ gap: 20px;
|
|
|
}
|
|
|
|
|
|
+.pick-btn,
|
|
|
.submit-btn {
|
|
|
- width: 100%;
|
|
|
+ flex: 1;
|
|
|
padding: 18px 0;
|
|
|
- background: #4a99e2;
|
|
|
border: none;
|
|
|
border-radius: 12px;
|
|
|
font-size: 24px;
|
|
|
@@ -891,17 +1162,284 @@ onMounted(() => {
|
|
|
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
|
|
}
|
|
|
|
|
|
+.pick-btn {
|
|
|
+ background: linear-gradient(90deg, #26dc8a 0%, #44efa2 100%);
|
|
|
+}
|
|
|
+
|
|
|
+.pick-btn:hover:not(:disabled) {
|
|
|
+ box-shadow: 0 0 30px rgba(42, 220, 138, 0.6);
|
|
|
+ transform: translateY(-2px);
|
|
|
+}
|
|
|
+
|
|
|
+.submit-btn {
|
|
|
+ background: #4a99e2;
|
|
|
+}
|
|
|
+
|
|
|
.submit-btn:hover:not(:disabled) {
|
|
|
box-shadow: 0 0 30px rgba(74, 153, 226, 0.6);
|
|
|
transform: translateY(-2px);
|
|
|
}
|
|
|
+ .location-select {
|
|
|
+ flex: 1;
|
|
|
+ min-width: 0;
|
|
|
+ }
|
|
|
|
|
|
+.pick-btn:disabled,
|
|
|
.submit-btn:disabled {
|
|
|
opacity: 0.5;
|
|
|
cursor: not-allowed;
|
|
|
background: linear-gradient(90deg, #6b7280 0%, #9ca3af 100%);
|
|
|
}
|
|
|
|
|
|
+/* ========== 配送方式选择区域(固定高度) ========== */
|
|
|
+.card-delivery-section {
|
|
|
+ padding: 10px 15px;
|
|
|
+ border-top: 1px solid rgba(30, 144, 255, 0.3);
|
|
|
+ background: rgba(9, 61, 140, 0.3);
|
|
|
+ min-height: 94px;
|
|
|
+ /* 固定最小高度 */
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ justify-content: center;
|
|
|
+ margin-bottom: 6px;
|
|
|
+}
|
|
|
+
|
|
|
+/* 未选中时的占位样式 */
|
|
|
+.delivery-placeholder {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ height: 100%;
|
|
|
+ color: #5a8abf;
|
|
|
+ font-size: 12px;
|
|
|
+ opacity: 0.7;
|
|
|
+}
|
|
|
+
|
|
|
+.delivery-row {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 8px;
|
|
|
+ margin-bottom: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.delivery-row:last-child {
|
|
|
+ margin-bottom: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.delivery-location-row {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 8px;
|
|
|
+ height: 30px;
|
|
|
+ margin-top: 6px;
|
|
|
+}
|
|
|
+
|
|
|
+.delivery-label {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #7ec8ff;
|
|
|
+ white-space: nowrap;
|
|
|
+}
|
|
|
+
|
|
|
+/* 配送方式按钮 */
|
|
|
+.delivery-method-buttons {
|
|
|
+ display: flex;
|
|
|
+ gap: 4px;
|
|
|
+}
|
|
|
+
|
|
|
+.delivery-btn {
|
|
|
+ display: inline-flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ gap: 3px;
|
|
|
+ padding: 4px 8px;
|
|
|
+ font-size: 11px;
|
|
|
+ font-weight: 500;
|
|
|
+ background: rgba(13, 58, 106, 0.8);
|
|
|
+ border: 1px solid #2a7fff;
|
|
|
+ color: #7ec8ff;
|
|
|
+ cursor: pointer;
|
|
|
+ transition: all 0.3s;
|
|
|
+ border-radius: 4px;
|
|
|
+}
|
|
|
+
|
|
|
+.delivery-btn i {
|
|
|
+ font-size: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.delivery-btn.active {
|
|
|
+ background: linear-gradient(90deg, #1e90ff 0%, #00bfff 100%);
|
|
|
+ color: #fff;
|
|
|
+ border-color: #00bfff;
|
|
|
+}
|
|
|
+
|
|
|
+.delivery-btn.disabled {
|
|
|
+ opacity: 0.4;
|
|
|
+ cursor: not-allowed;
|
|
|
+}
|
|
|
+
|
|
|
+.delivery-btn:hover:not(.disabled):not(.active) {
|
|
|
+ background: rgba(30, 144, 255, 0.3);
|
|
|
+}
|
|
|
+
|
|
|
+/* 配送类型徽章 */
|
|
|
+.delivery-type-badge {
|
|
|
+ padding: 3px 10px;
|
|
|
+ border-radius: 12px;
|
|
|
+ font-size: 10px;
|
|
|
+ font-weight: 500;
|
|
|
+ display: inline-block;
|
|
|
+}
|
|
|
+
|
|
|
+.delivery-type-badge.badge-manual {
|
|
|
+ background: rgba(107, 114, 128, 0.4);
|
|
|
+ border: 1px solid #6b7280;
|
|
|
+ color: #d1d5db;
|
|
|
+}
|
|
|
+
|
|
|
+.delivery-type-badge.badge-agv-force {
|
|
|
+ background: rgba(234, 88, 12, 0.4);
|
|
|
+ border: 1px solid #ea580c;
|
|
|
+ color: #fdba74;
|
|
|
+}
|
|
|
+
|
|
|
+.delivery-type-badge.badge-agv-optional {
|
|
|
+ background: rgba(16, 185, 129, 0.4);
|
|
|
+ border: 1px solid #10b981;
|
|
|
+ color: #6ee7b7;
|
|
|
+}
|
|
|
+
|
|
|
+/* ========== 科技感弹窗样式 ========== */
|
|
|
+.tech-modal-overlay {
|
|
|
+ position: fixed;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ background: rgba(4, 28, 61, 0.8);
|
|
|
+ backdrop-filter: blur(8px);
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ z-index: 1000;
|
|
|
+}
|
|
|
+
|
|
|
+.tech-modal {
|
|
|
+ background: linear-gradient(135deg, rgba(9, 61, 140, 0.95) 0%, rgba(4, 28, 61, 0.98) 100%);
|
|
|
+ border: 2px solid #049FD8;
|
|
|
+ border-radius: 20px;
|
|
|
+ padding: 40px;
|
|
|
+ min-width: 500px;
|
|
|
+ max-width: 90vw;
|
|
|
+ box-shadow: 0 0 50px rgba(4, 159, 216, 0.4);
|
|
|
+ position: relative;
|
|
|
+}
|
|
|
+
|
|
|
+.tech-modal.success-modal {
|
|
|
+ border-color: #10b981;
|
|
|
+ box-shadow: 0 0 50px rgba(16, 185, 129, 0.4);
|
|
|
+}
|
|
|
+
|
|
|
+.modal-content-row {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 30px;
|
|
|
+ margin-bottom: 40px;
|
|
|
+}
|
|
|
+
|
|
|
+.modal-text {
|
|
|
+ flex: 1;
|
|
|
+}
|
|
|
+
|
|
|
+.modal-text h3 {
|
|
|
+ font-size: 32px;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #fff;
|
|
|
+ margin: 0 0 15px 0;
|
|
|
+}
|
|
|
+
|
|
|
+.modal-text p {
|
|
|
+ font-size: 18px;
|
|
|
+ color: #7ec8ff;
|
|
|
+ margin: 0;
|
|
|
+ line-height: 1.6;
|
|
|
+}
|
|
|
+
|
|
|
+.modal-icon {
|
|
|
+ flex-shrink: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.icon-box {
|
|
|
+ width: 80px;
|
|
|
+ height: 80px;
|
|
|
+ border-radius: 50%;
|
|
|
+ background: linear-gradient(135deg, #1e90ff 0%, #00bfff 100%);
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ font-size: 40px;
|
|
|
+ color: #fff;
|
|
|
+ position: relative;
|
|
|
+ box-shadow: 0 0 20px rgba(0, 191, 255, 0.4);
|
|
|
+}
|
|
|
+
|
|
|
+.icon-box.success-box {
|
|
|
+ background: linear-gradient(135deg, #10b981 0%, #34d399 100%);
|
|
|
+ box-shadow: 0 0 20px rgba(16, 185, 129, 0.4);
|
|
|
+}
|
|
|
+
|
|
|
+.check-icon {
|
|
|
+ position: absolute;
|
|
|
+ top: -5px;
|
|
|
+ right: -5px;
|
|
|
+ width: 30px;
|
|
|
+ height: 30px;
|
|
|
+ background: linear-gradient(135deg, #22c55e 0%, #16a34a 100%);
|
|
|
+ border-radius: 50%;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ font-size: 16px;
|
|
|
+ color: #fff;
|
|
|
+}
|
|
|
+
|
|
|
+.modal-footer {
|
|
|
+ display: flex;
|
|
|
+ gap: 20px;
|
|
|
+ justify-content: flex-end;
|
|
|
+}
|
|
|
+
|
|
|
+.modal-btn {
|
|
|
+ padding: 15px 40px;
|
|
|
+ border: none;
|
|
|
+ border-radius: 12px;
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: bold;
|
|
|
+ cursor: pointer;
|
|
|
+ transition: all 0.3s;
|
|
|
+ min-width: 120px;
|
|
|
+}
|
|
|
+
|
|
|
+.cancel-btn {
|
|
|
+ background: rgba(107, 114, 128, 0.8);
|
|
|
+ color: #fff;
|
|
|
+ border: 1px solid #6b7280;
|
|
|
+}
|
|
|
+
|
|
|
+.cancel-btn:hover {
|
|
|
+ background: rgba(75, 85, 99, 0.9);
|
|
|
+ box-shadow: 0 0 15px rgba(107, 114, 128, 0.4);
|
|
|
+}
|
|
|
+
|
|
|
+.confirm-btn {
|
|
|
+ background: linear-gradient(90deg, #1e90ff 0%, #00bfff 100%);
|
|
|
+ color: #fff;
|
|
|
+}
|
|
|
+
|
|
|
+.confirm-btn:hover {
|
|
|
+ box-shadow: 0 0 25px rgba(30, 144, 255, 0.6);
|
|
|
+ transform: translateY(-2px);
|
|
|
+}
|
|
|
+
|
|
|
/* ========== 响应式 - 1920x1080 横屏 ========== */
|
|
|
@media screen and (orientation: landscape) {
|
|
|
.stock-requisition-page {
|
|
|
@@ -1124,5 +1662,14 @@ onMounted(() => {
|
|
|
.card-grid-wrapper::-webkit-scrollbar {
|
|
|
display: none;
|
|
|
}
|
|
|
+ :deep(.dark-select .vs__dropdown-toggle) {
|
|
|
+ min-height: 48px;
|
|
|
+ padding: 8px 14px;
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.dark-select .vs__dropdown-option) {
|
|
|
+ padding: 12px 18px;
|
|
|
+ font-size: 16px;
|
|
|
+ }
|
|
|
}
|
|
|
</style>
|