|
|
@@ -1,4 +1,4 @@
|
|
|
-<!-- 出库确认 - 智能仓储风格 -->
|
|
|
+<!-- 借用 - 智能仓储风格 -->
|
|
|
<template>
|
|
|
<dv-border-box-8>
|
|
|
<div class="stock-requisition-page">
|
|
|
@@ -11,10 +11,10 @@
|
|
|
<i class="fas fa-home" />
|
|
|
<span>主页</span>
|
|
|
</button>
|
|
|
- <h1 class="page-title">出库确认</h1>
|
|
|
+ <h1 class="page-title">借用</h1>
|
|
|
<!-- 右侧操作按钮 -->
|
|
|
<div class="header-actions">
|
|
|
- <button class="action-btn refresh-btn" @click="getStockOutList(false)">
|
|
|
+ <button class="action-btn refresh-btn" @click="resetView">
|
|
|
<i class="fas fa-sync-alt" />
|
|
|
<span>重新校验</span>
|
|
|
</button>
|
|
|
@@ -25,7 +25,8 @@
|
|
|
<main class="main-content">
|
|
|
<!-- 统计信息 -->
|
|
|
<div v-if="materialList.length > 0" class="stats-section">
|
|
|
- <span class="stats-text">共 {{ materialList.length }} 条数据,已完成 {{ completedCount }} 条</span>
|
|
|
+ <!-- <span class="stats-text">共 {{ materialList.length }} 条数据,已完成 {{ completedCount }} 条</span> -->
|
|
|
+ <span class="stats-text">共 {{ materialList.length }} 条数据,不识别 {{ unrecognizedCount }} 条</span>
|
|
|
</div>
|
|
|
|
|
|
<!-- 卡片网格区域 -->
|
|
|
@@ -38,64 +39,82 @@
|
|
|
|
|
|
<!-- 卡片网格 -->
|
|
|
<div v-else class="card-grid">
|
|
|
- <div
|
|
|
- v-for="(item, index) in materialList"
|
|
|
- :key="item.inventoryId || index"
|
|
|
- class="inventory-card"
|
|
|
- :class="{ 'completed': item.status === 1 }"
|
|
|
- >
|
|
|
- <!-- 卡片序号 -->
|
|
|
- <div class="card-index" :class="{ 'completed': item.status === 1 }">{{ index + 1 }}</div>
|
|
|
-
|
|
|
- <!-- 图片区域 -->
|
|
|
- <div class="card-image">
|
|
|
- <div class="image-placeholder" :style="{ backgroundColor: getStatusColor(item.status) }">
|
|
|
- <i :class="getInventoryIcon(item.inventoryType)" />
|
|
|
+ <template v-for="(item, index) in validMaterialList" :key="item.inventoryId || index">
|
|
|
+ <div
|
|
|
+ class="inventory-card"
|
|
|
+ :class="{
|
|
|
+ 'completed': item.status === 1 || item.status === 3,
|
|
|
+ 'not-selectable': item.positionName === '不在库' || item.inventoryName === '未识别epc'
|
|
|
+ }"
|
|
|
+ >
|
|
|
+ <!-- @click="handleSelect(item)" -->
|
|
|
+ <!-- 'selected': item.selected, -->
|
|
|
+ <!-- 'warning': item.status === 2 || item.status === 3, -->
|
|
|
+ <!-- 卡片序号 -->
|
|
|
+ <div class="card-index" :class="{ 'completed': item.status === 1 }">{{ index + 1 }}</div>
|
|
|
+
|
|
|
+ <!-- 信息区域 -->
|
|
|
+ <div class="card-info">
|
|
|
+ <div class="info-row">
|
|
|
+ <span class="info-label">名称:</span>
|
|
|
+ <span class="info-value">{{ item.inventoryName || '-' }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="info-row">
|
|
|
+ <span class="info-label">编号:</span>
|
|
|
+ <span class="info-value">{{ item.inventoryNo || '-' }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="info-row">
|
|
|
+ <span class="info-label">类型:</span>
|
|
|
+ <span class="info-value">{{ item.inventoryType || '-' }}</span>
|
|
|
+ <i :class="getInventoryIcon(item.inventoryType)" class="type-icon" />
|
|
|
+ </div>
|
|
|
+ <div class="info-row location-row">
|
|
|
+ <i class="fas fa-map-marker-alt location-icon" />
|
|
|
+ <span class="info-value">{{ item.positionName || '-' }} / {{ item.warehouseName || '-' }}</span>
|
|
|
+ </div>
|
|
|
+ <!-- 不在库的借用人信息显示在内容区域 -->
|
|
|
+ <div v-if="item.positionName === '不在库'" class="info-row borrower-row">
|
|
|
+ <span class="info-label">借用人:</span>
|
|
|
+ <span class="info-value">{{ item.borrower || '-' }}</span>
|
|
|
+ </div>
|
|
|
+ <div v-else class="borrower-row">
|
|
|
+ <span class="info-label">-</span>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
|
|
|
- <!-- 信息区域 -->
|
|
|
- <div class="card-info">
|
|
|
- <div class="info-row">
|
|
|
- <span class="info-label">名称:</span>
|
|
|
- <span class="info-value">{{ item.inventoryName || '-' }}</span>
|
|
|
- </div>
|
|
|
- <div class="info-row">
|
|
|
- <span class="info-label">编号:</span>
|
|
|
- <span class="info-value">{{ item.inventoryNo || '-' }}</span>
|
|
|
+ <!-- 操作区域(固定高度) -->
|
|
|
+ <div class="card-action-section">
|
|
|
+ <template v-if="item.positionName !== '不在库' && item.inventoryName !== '未识别epc'">
|
|
|
+ <button v-if="item.status === 1 || item.status === 3" class="status-btn apply-btn" @click.stop="handleApply(item)">
|
|
|
+ <i class="fas fa-hand-paper" /> 借用
|
|
|
+ </button>
|
|
|
+ </template>
|
|
|
+ <template v-else-if="item.positionName === '不在库'">
|
|
|
+ <div class="status-badge borrowed-badge">
|
|
|
+ <i class="fas fa-exclamation-circle" />
|
|
|
+ 已借用
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <span class="status-placeholder">无需操作</span>
|
|
|
+ </template>
|
|
|
</div>
|
|
|
- <div class="info-row location-row">
|
|
|
- <i class="fas fa-map-marker-alt location-icon" />
|
|
|
- <span class="info-value">{{ item.positionName || '-' }} / {{ item.warehouseName || '-' }}</span>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
|
|
|
- <!-- 操作区域(固定高度) -->
|
|
|
- <div class="card-action-section">
|
|
|
- <template v-if="item.positionName !== '不在库' && item.inventoryName !== '未识别epc'">
|
|
|
- <button v-if="item.status === 1" class="status-btn completed-btn" disabled>
|
|
|
- <i class="fas fa-check" /> 领料完成
|
|
|
- </button>
|
|
|
- <button v-if="item.status === 2" class="status-btn start-btn" @click.stop="handleStart(item)">
|
|
|
- <i class="fas fa-play" /> 开始领料
|
|
|
- </button>
|
|
|
- <button v-if="item.status === 3" class="status-btn apply-btn" @click.stop="handleApply(item)">
|
|
|
- <i class="fas fa-hand-paper" /> 申请领料
|
|
|
- </button>
|
|
|
- </template>
|
|
|
- <template v-else>
|
|
|
- <span class="status-placeholder">无需操作</span>
|
|
|
- </template>
|
|
|
+ <!-- 选中状态指示 -->
|
|
|
+ <!-- <div v-if="item.selected" class="selected-indicator">
|
|
|
+ <i class="fas fa-check" />
|
|
|
+ </div> -->
|
|
|
</div>
|
|
|
- </div>
|
|
|
+ </template>
|
|
|
</div>
|
|
|
</div>
|
|
|
</main>
|
|
|
|
|
|
<!-- 底部操作按钮 -->
|
|
|
<div class="bottom-actions">
|
|
|
- <button class="submit-btn" :disabled="!isCanLeave" @click="handleLeave">
|
|
|
- 领料离开
|
|
|
+ <button class="submit-btn" @click="hasValidMaterials ? handleLeaveClick() : directExit()">
|
|
|
+ {{ hasValidMaterials ? '借用离开' : '直接出仓库' }}
|
|
|
+ <span v-if="hasValidMaterials && selectedCount > 0">({{ selectedCount }})</span>
|
|
|
</button>
|
|
|
</div>
|
|
|
|
|
|
@@ -106,7 +125,28 @@
|
|
|
<div class="dot" />
|
|
|
<div class="dot" />
|
|
|
</div>
|
|
|
- <span class="loading-text">加载中...</span>
|
|
|
+ <span class="loading-text">执行中...</span>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 直接出仓库确认弹窗 -->
|
|
|
+ <div v-if="exitConfirmVisible" class="tech-modal-overlay" @click.self="exitConfirmVisible = false">
|
|
|
+ <div class="tech-modal">
|
|
|
+ <div class="modal-content-row">
|
|
|
+ <div class="modal-text">
|
|
|
+ <h3>请确认您要直接出仓库</h3>
|
|
|
+ <p>系统检测到您未携带物料,或者未勾选任何物料,是否确认直接出仓库?</p>
|
|
|
+ </div>
|
|
|
+ <div class="modal-icon">
|
|
|
+ <div class="icon-box">
|
|
|
+ <i class="fas fa-clipboard-check" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="modal-footer">
|
|
|
+ <button class="modal-btn cancel-btn" @click="directExit">直接出仓库</button>
|
|
|
+ <button class="modal-btn confirm-btn" @click="exitConfirmVisible = false">取消</button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</dv-border-box-8>
|
|
|
@@ -187,97 +227,200 @@ const isCanLeave = computed(() => {
|
|
|
});
|
|
|
});
|
|
|
|
|
|
-// 开始领料
|
|
|
+const unrecognizedCount = computed(() => {
|
|
|
+ return materialList.value.filter(item => item.inventoryId == null).length;
|
|
|
+});
|
|
|
+
|
|
|
+// 选中数量统计
|
|
|
+const selectedCount = computed(() => {
|
|
|
+ return materialList.value.filter(item => item.selected === true).length;
|
|
|
+});
|
|
|
+
|
|
|
+// 判断是否有有效物料(含有inventoryId)
|
|
|
+const hasValidMaterials = computed(() => {
|
|
|
+ return materialList.value.length > 0 && materialList.value.some(item => item.inventoryId != null);
|
|
|
+});
|
|
|
+
|
|
|
+// 过滤出有效的物料项目(用于连续序号显示)
|
|
|
+const validMaterialList = computed(() => {
|
|
|
+ return materialList.value.filter(item => item.inventoryId != null);
|
|
|
+});
|
|
|
+
|
|
|
+// 卡片选择处理
|
|
|
+const handleSelect = item => {
|
|
|
+ // 不在库和未识别epc的卡片不可选中
|
|
|
+ if (item.positionName === '不在库' || item.inventoryName === '未识别epc') {
|
|
|
+ showNotify({ type: 'danger', message: '不在库或尚未借用的卡片不可选中' });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 只有已借用状态(status === 1)的卡片才可被勾选
|
|
|
+ if (item.status !== 1) {
|
|
|
+ showNotify({ type: 'danger', message: '只有已借用状态的卡片才可被勾选' });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ item.selected = !item.selected;
|
|
|
+};
|
|
|
+
|
|
|
+// 弹窗状态
|
|
|
+const exitConfirmVisible = ref(false);
|
|
|
+
|
|
|
+// 处理离开按钮点击
|
|
|
+const handleLeaveClick = () => {
|
|
|
+ gateController('SHOTOPEN');
|
|
|
+ router.push('/');
|
|
|
+ // if (selectedCount.value === 0) {
|
|
|
+ // exitConfirmVisible.value = true;
|
|
|
+ // return;
|
|
|
+ // }
|
|
|
+ // handleLeave();
|
|
|
+};
|
|
|
+
|
|
|
+// 直接出仓库
|
|
|
+const directExit = () => {
|
|
|
+ exitConfirmVisible.value = false;
|
|
|
+ // 直接开门离开
|
|
|
+ gateController('SHOTOPEN');
|
|
|
+ router.push('/');
|
|
|
+};
|
|
|
+
|
|
|
+// 开始借用
|
|
|
const handleStart = record => {
|
|
|
operationId.value = record.inventoryId;
|
|
|
generateCFStockOut(record.stockOutPrepareLineId);
|
|
|
};
|
|
|
|
|
|
-// 申请领料
|
|
|
+// 借用
|
|
|
const handleApply = async record => {
|
|
|
- showNotify({ type: 'success', message: '申请领料成功' });
|
|
|
+ showNotify({ type: 'success', message: '申请借用成功' });
|
|
|
try {
|
|
|
const res = await leaveCFWarehouse(record.inventoryId);
|
|
|
|
|
|
if (res.errorCode === 0) {
|
|
|
- showNotify({ type: 'success', message: '申请领料成功' });
|
|
|
+ showNotify({ type: 'success', message: '申请借用成功' });
|
|
|
operationId.value = record.inventoryId;
|
|
|
- getStockOutList(true);
|
|
|
+ if(res.data){
|
|
|
+ materialList.value.forEach(item =>{
|
|
|
+ if(item.inventoryId == res.data.inventoryId){
|
|
|
+ // item.status = res.data.status;
|
|
|
+ // item.stockOutId = res.data.stockOutId;
|
|
|
+ // item.stockOutPrepareLineId = res.data.stockOutPrepareLineId;
|
|
|
+ item.borrower = res.data.borrower;
|
|
|
+ item.epc = res.data.epc;
|
|
|
+ item.inventoryName = res.data.inventoryName;
|
|
|
+ item.inventoryType = res.data.inventoryType;
|
|
|
+ item.warehouseName = res.data.warehouseName;
|
|
|
+ item.positionName = res.data.positionName;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
} else {
|
|
|
showNotify({ type: 'danger', message: res.errorMessage });
|
|
|
}
|
|
|
} catch (error) {
|
|
|
- console.error('申请领料API调用失败:', error);
|
|
|
- showNotify({ type: 'danger', message: '申请领料API调用失败' });
|
|
|
+ console.error('申请借用API调用失败:', error);
|
|
|
+ showNotify({ type: 'danger', message: '申请借用API调用失败' });
|
|
|
} finally {
|
|
|
loading.value = false;
|
|
|
}
|
|
|
};
|
|
|
|
|
|
-// 领料完成后离开
|
|
|
+// 借用完成后离开
|
|
|
const handleLeave = async () => {
|
|
|
- const params = materialList.value.map(item => {
|
|
|
- return {
|
|
|
- stockOutPrepareLineId: item.stockOutPrepareLineId,
|
|
|
- stockOutId: item.stockOutId,
|
|
|
- inventoryId: item.inventoryId,
|
|
|
- };
|
|
|
+ const params = [];
|
|
|
+ materialList.value.map(item => {
|
|
|
+ if(item.inventoryId != null && item.selected === true){
|
|
|
+ params.push({
|
|
|
+ stockOutPrepareLineId: item.stockOutPrepareLineId,
|
|
|
+ stockOutId: item.stockOutId,
|
|
|
+ inventoryId: item.inventoryId,
|
|
|
+ });
|
|
|
+ }
|
|
|
});
|
|
|
+ if(params.length == 0){
|
|
|
+ // 直接开门离开
|
|
|
+ gateController('SHOTOPEN');
|
|
|
+ router.push('/');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
loading.value = true;
|
|
|
try {
|
|
|
const res = await cfStockOutLeave(params);
|
|
|
|
|
|
if (res.errorCode === 0) {
|
|
|
gateController('SHOTOPEN');
|
|
|
- showNotify({ type: 'success', message: '领料离开成功' });
|
|
|
+ showNotify({ type: 'success', message: '借用离开成功' });
|
|
|
router.push('/');
|
|
|
} else {
|
|
|
showNotify({ type: 'danger', message: res.errorMessage });
|
|
|
}
|
|
|
} catch (error) {
|
|
|
- console.error('领料离开API调用失败:', error);
|
|
|
- showNotify({ type: 'danger', message: '领料离开API调用失败' });
|
|
|
+ console.error('借用离开API调用失败:', error);
|
|
|
+ showNotify({ type: 'danger', message: '借用离开API调用失败' });
|
|
|
} finally {
|
|
|
loading.value = false;
|
|
|
}
|
|
|
};
|
|
|
|
|
|
-// 获取扫描到的领料数据
|
|
|
-const getStockOutList = async (isOne = false) => {
|
|
|
+const resetView = () => {
|
|
|
+ materialList.value = [];
|
|
|
+};
|
|
|
+
|
|
|
+// 获取扫描到的借用数据
|
|
|
+const getStockOutList = async () => {
|
|
|
// loading.value = true;
|
|
|
const params = {
|
|
|
- epcList: epcs.value,
|
|
|
+ epcList: [],
|
|
|
};
|
|
|
+
|
|
|
+ const tempMaterialList = [];
|
|
|
+
|
|
|
+ for(let i = 0; i < materialList.value.length; i++) {
|
|
|
+ if(materialList.value[i].queryStatus === 0) {
|
|
|
+ params.epcList.push(materialList.value[i].epc);
|
|
|
+ materialList.value[i].queryStatus = 1;
|
|
|
+ tempMaterialList.push(materialList.value[i]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if(params.epcList.length == 0){
|
|
|
+ return;
|
|
|
+ }
|
|
|
try {
|
|
|
const res = await cfStockOut(params);
|
|
|
|
|
|
if (res.errorCode === 0) {
|
|
|
if (res.datas && res.datas.length > 0) {
|
|
|
- if (!isOne) {
|
|
|
- materialList.value = [];
|
|
|
- materialList.value = res.datas;
|
|
|
- } else {
|
|
|
- res.datas.forEach(i => {
|
|
|
- materialList.value.forEach(j => {
|
|
|
- if (j.inventoryId === operationId.value) {
|
|
|
- j.status = 1;
|
|
|
- j.stockOutId = i.stockOutId;
|
|
|
- j.positionName = i.positionName;
|
|
|
- j.warehouseName = i.warehouseName;
|
|
|
- j.stockOutPrepareLineId = i.stockOutPrepareLineId;
|
|
|
- }
|
|
|
- });
|
|
|
+ res.datas.forEach(i => {
|
|
|
+ materialList.value.forEach(j => {
|
|
|
+ if (j.epc === i.epc) {
|
|
|
+ j.stockOutId = i.stockOutId;
|
|
|
+ j.inventoryName = i.inventoryName;
|
|
|
+ j.inventoryNo = i.inventoryNo;
|
|
|
+ j.inventoryType = i.inventoryType;
|
|
|
+ j.borrower = i.borrower;
|
|
|
+ j.warehouseName = i.warehouseName;
|
|
|
+ j.positionName = i.positionName;
|
|
|
+ j.stockOutPrepareNo = i.stockOutPrepareNo;
|
|
|
+ j.stockOutNo = i.stockOutNo;
|
|
|
+ j.inventoryId = i.inventoryId;
|
|
|
+ j.stockOutPrepareLineId = i.stockOutPrepareLineId;
|
|
|
+ j.queryStatus = 2;
|
|
|
+ j.status = i.status;
|
|
|
+ }
|
|
|
});
|
|
|
- }
|
|
|
- } else {
|
|
|
- materialList.value = [];
|
|
|
+ });
|
|
|
}
|
|
|
} else {
|
|
|
showNotify({ type: 'danger', message: res.errorMessage });
|
|
|
}
|
|
|
} catch (error) {
|
|
|
- console.error('获取扫描到的领料数据API调用失败:', error);
|
|
|
- showNotify({ type: 'danger', message: '获取扫描到的领料数据API调用失败' });
|
|
|
+ console.error('获取扫描到的借用数据API调用失败:', error);
|
|
|
+ showNotify({ type: 'danger', message: '获取扫描到的借用数据API调用失败' });
|
|
|
+ tempMaterialList.forEach(item => {
|
|
|
+ item.queryStatus = 0;
|
|
|
+ });
|
|
|
} finally {
|
|
|
loading.value = false;
|
|
|
}
|
|
|
@@ -296,7 +439,8 @@ const generateCFStockOut = async id => {
|
|
|
const res = await createStockOut(params);
|
|
|
|
|
|
if (res.errorCode === 0) {
|
|
|
- getStockOutList(true);
|
|
|
+ // getStockOutList();
|
|
|
+ resetView();
|
|
|
} else {
|
|
|
showNotify({ type: 'danger', message: res.errorMessage });
|
|
|
}
|
|
|
@@ -315,12 +459,29 @@ const addEpc = data => {
|
|
|
const newEpcs = data.map(item => item.epc);
|
|
|
|
|
|
// 将新的EPC数据添加到临时数组中,使用Set进行去重
|
|
|
- const uniqueEpcs = new Set([...tempEpcs.value, ...newEpcs]);
|
|
|
- tempEpcs.value = [...uniqueEpcs];
|
|
|
+ const uniqueEpcs = new Set([...newEpcs]);
|
|
|
+
|
|
|
+ if(newEpcs != null && newEpcs.length > 0) {
|
|
|
+ newEpcs.forEach(item => {
|
|
|
+ let exist = false;
|
|
|
+ for(let i =0; i < materialList.value.length; i++) {
|
|
|
+ if(materialList.value[i].epc === item) {
|
|
|
+ exist = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(exist == false) {
|
|
|
+ materialList.value.push({
|
|
|
+ epc: item,
|
|
|
+ queryStatus: 0, // 0: 未查询, 1: 查询中, 2: 已查询, 3: 未查询到
|
|
|
+ selected: false, // 初始化选中状态
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
onMounted(() => {
|
|
|
- // getStockOutList(false);
|
|
|
plugin.gateConfig.sendEpc = function(data){
|
|
|
if (typeof(GATE_CONFIG) == 'undefined') {
|
|
|
console.log('设备不支持读写器功能。');
|
|
|
@@ -331,13 +492,27 @@ onMounted(() => {
|
|
|
|
|
|
// 创建全局唯一定时器,每2秒执行一次
|
|
|
timer = setInterval(() => {
|
|
|
- // 将临时数组的数据赋值给epcs
|
|
|
- epcs.value = [...tempEpcs.value];
|
|
|
- // 执行获取出库列表
|
|
|
- getStockOutList(false);
|
|
|
- // 清空临时数组
|
|
|
- tempEpcs.value = [];
|
|
|
- }, 3000);
|
|
|
+ getStockOutList();
|
|
|
+ // addEpc([{
|
|
|
+ // 'epc': 'FFF000000000000000000001',
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // 'epc': 'AAA000000000000000000002',
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // 'epc': 'EEE000000637713102889024',
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // 'epc': 'EEE000000640804317954113',
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // 'epc': 'EEE000000639032505671744',
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // 'epc': 'EEE000000640804317955613',
|
|
|
+ // },
|
|
|
+ // ]);
|
|
|
+ }, 1000);
|
|
|
});
|
|
|
|
|
|
onUnmounted(() => {
|
|
|
@@ -472,6 +647,36 @@ onUnmounted(() => {
|
|
|
box-shadow: 0 0 15px rgba(16, 185, 129, 0.3);
|
|
|
}
|
|
|
|
|
|
+.inventory-card.warning {
|
|
|
+ border-color: #fbbf24 !important;
|
|
|
+ box-shadow: 0 0 15px rgba(251, 191, 36, 0.4) !important;
|
|
|
+}
|
|
|
+
|
|
|
+.inventory-card.selected {
|
|
|
+ border-color: #fbbf24;
|
|
|
+ box-shadow: 0 0 20px rgba(251, 191, 36, 0.4);
|
|
|
+ background: rgba(251, 191, 36, 0.1);
|
|
|
+}
|
|
|
+
|
|
|
+/* 选中状态指示 - 右上角 */
|
|
|
+.selected-indicator {
|
|
|
+ position: absolute;
|
|
|
+ top: 10px;
|
|
|
+ right: 10px;
|
|
|
+ width: 28px;
|
|
|
+ height: 28px;
|
|
|
+ background: linear-gradient(135deg, #10b981 0%, #34d399 100%);
|
|
|
+ border-radius: 50%;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ color: white;
|
|
|
+ font-size: 12px;
|
|
|
+ font-weight: bold;
|
|
|
+ box-shadow: 0 2px 8px rgba(16, 185, 129, 0.4);
|
|
|
+ z-index: 10;
|
|
|
+}
|
|
|
+
|
|
|
/* 卡片序号 - 左上角 */
|
|
|
.card-index {
|
|
|
position: absolute;
|
|
|
@@ -492,49 +697,74 @@ onUnmounted(() => {
|
|
|
}
|
|
|
|
|
|
.card-index.completed {
|
|
|
- background: linear-gradient(135deg, #10b981 0%, #34d399 100%);
|
|
|
+ /* background: linear-gradient(135deg, #10b981 0%, #34d399 100%); */
|
|
|
box-shadow: 0 2px 8px rgba(16, 185, 129, 0.4);
|
|
|
}
|
|
|
|
|
|
-/* 图片区域 */
|
|
|
-.card-image {
|
|
|
- width: 100%;
|
|
|
- aspect-ratio: 3 / 4;
|
|
|
+/* 类型图标样式 */
|
|
|
+.type-icon {
|
|
|
+ color: #fbbf24;
|
|
|
+ margin-left: 8px;
|
|
|
+ font-size: 16px;
|
|
|
+}
|
|
|
+
|
|
|
+/* 不可选择的卡片 - 红色边框 */
|
|
|
+.inventory-card.not-selectable {
|
|
|
+ border-color: #ef4444 !important;
|
|
|
+ box-shadow: 0 0 15px rgba(239, 68, 68, 0.3) !important;
|
|
|
+ cursor: not-allowed;
|
|
|
+}
|
|
|
+
|
|
|
+.inventory-card.not-selectable:hover {
|
|
|
+ border-color: #dc2626 !important;
|
|
|
+ box-shadow: 0 0 20px rgba(220, 38, 38, 0.4) !important;
|
|
|
+ transform: none;
|
|
|
+}
|
|
|
+
|
|
|
+/* 借用人信息样式 */
|
|
|
+.borrower-info {
|
|
|
display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- overflow: hidden;
|
|
|
- margin: 15px;
|
|
|
- margin-bottom: 10px;
|
|
|
- border-radius: 8px;
|
|
|
- width: calc(100% - 30px);
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 8px;
|
|
|
+ padding: 8px 0;
|
|
|
+ min-height: 48px; /* 确保与按钮区域高度一致 */
|
|
|
}
|
|
|
|
|
|
-.image-placeholder {
|
|
|
+.borrower-row {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
- justify-content: center;
|
|
|
- width: 100%;
|
|
|
- height: 100%;
|
|
|
- background: linear-gradient(135deg, #f0f4f8 0%, #e8ecf0 100%);
|
|
|
+ font-size: 14px;
|
|
|
+ border-bottom: 1px solid rgba(126, 200, 255, 0.2) !important;
|
|
|
+}
|
|
|
+
|
|
|
+.borrower-label {
|
|
|
+ color: #7ec8ff;
|
|
|
+ white-space: nowrap;
|
|
|
+ margin-right: 5px;
|
|
|
+}
|
|
|
+
|
|
|
+.borrower-value {
|
|
|
color: #fff;
|
|
|
- font-size: 48px;
|
|
|
+ flex: 1;
|
|
|
}
|
|
|
|
|
|
/* 信息区域 */
|
|
|
.card-info {
|
|
|
- padding: 10px 15px 15px;
|
|
|
+ padding: 50px 15px 15px;
|
|
|
}
|
|
|
|
|
|
.info-row {
|
|
|
display: flex;
|
|
|
- align-items: baseline;
|
|
|
- margin-bottom: 6px;
|
|
|
+ align-items: center;
|
|
|
+ padding: 6px 0; /* 增加内容块高度 */
|
|
|
font-size: 14px;
|
|
|
+ min-height: 28px; /* 增加最小高度 */
|
|
|
+ border-bottom: 1px solid rgba(126, 200, 255, 0.2); /* 添加分割线 */
|
|
|
+ margin-bottom: 0;
|
|
|
}
|
|
|
|
|
|
.info-row:last-child {
|
|
|
- margin-bottom: 0;
|
|
|
+ border-bottom: none; /* 最后一行不显示分割线 */
|
|
|
}
|
|
|
|
|
|
.info-label {
|
|
|
@@ -556,8 +786,9 @@ onUnmounted(() => {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
margin-top: 4px;
|
|
|
- padding-top: 4px;
|
|
|
- border-top: 1px solid rgba(30, 144, 255, 0.2);
|
|
|
+ /* padding-top: 4px; */
|
|
|
+ /* border-top: 1px solid rgba(30, 144, 255, 0.2); */
|
|
|
+ border-bottom: 1px solid rgba(30, 144, 255, 0.2) !important;
|
|
|
}
|
|
|
|
|
|
.location-icon {
|
|
|
@@ -568,19 +799,19 @@ onUnmounted(() => {
|
|
|
|
|
|
/* ========== 操作区域(固定高度) ========== */
|
|
|
.card-action-section {
|
|
|
- padding: 12px 15px;
|
|
|
- border-top: 1px solid rgba(30, 144, 255, 0.3);
|
|
|
- background: rgba(9, 61, 140, 0.3);
|
|
|
- min-height: 50px;
|
|
|
+ padding: 8px 15px;
|
|
|
+ min-height: 48px;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
|
+ /* 移除边框和背景色差异,与无需操作区域保持一致 */
|
|
|
}
|
|
|
|
|
|
.status-placeholder {
|
|
|
color: #5a8abf;
|
|
|
- font-size: 12px;
|
|
|
- opacity: 0.7;
|
|
|
+ font-size: 14px;
|
|
|
+ opacity: 0.8;
|
|
|
+ margin-top: -10px;
|
|
|
}
|
|
|
|
|
|
/* 状态按钮 */
|
|
|
@@ -624,6 +855,31 @@ onUnmounted(() => {
|
|
|
box-shadow: 0 0 15px rgba(30, 144, 255, 0.5);
|
|
|
}
|
|
|
|
|
|
+.in-stock-btn {
|
|
|
+ background: linear-gradient(90deg, #10b981 0%, #34d399 100%);
|
|
|
+ color: #fff;
|
|
|
+ opacity: 0.8;
|
|
|
+ cursor: default;
|
|
|
+}
|
|
|
+
|
|
|
+/* 状态徽章样式 */
|
|
|
+.status-badge {
|
|
|
+ padding: 8px 20px;
|
|
|
+ border-radius: 20px;
|
|
|
+ font-size: 13px;
|
|
|
+ font-weight: 500;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 6px;
|
|
|
+}
|
|
|
+
|
|
|
+.borrowed-badge {
|
|
|
+ background: rgba(239, 68, 68, 0.3);
|
|
|
+ border: 1px solid #ef4444;
|
|
|
+ color: #fca5a5;
|
|
|
+ margin-top: -10px;
|
|
|
+}
|
|
|
+
|
|
|
/* ========== 底部操作按钮 ========== */
|
|
|
.bottom-actions {
|
|
|
width: 100%;
|
|
|
@@ -731,7 +987,7 @@ onUnmounted(() => {
|
|
|
}
|
|
|
|
|
|
.card-info {
|
|
|
- padding: 6px 10px 8px;
|
|
|
+ padding: 32px 10px 8px;
|
|
|
}
|
|
|
|
|
|
.info-row {
|
|
|
@@ -749,13 +1005,13 @@ onUnmounted(() => {
|
|
|
}
|
|
|
|
|
|
.status-btn {
|
|
|
- padding: 6px 10px;
|
|
|
+ padding: 10px;
|
|
|
font-size: 11px;
|
|
|
gap: 4px;
|
|
|
}
|
|
|
|
|
|
.status-placeholder {
|
|
|
- font-size: 10px;
|
|
|
+ font-size: 14px;
|
|
|
}
|
|
|
|
|
|
.bottom-actions {
|