| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010 |
- <!-- 借用 - 智能仓储风格 -->
- <template>
- <dv-border-box-8>
- <div class="stock-requisition-page">
- <!-- 背景层 -->
- <div class="bg-layer" :style="{ backgroundImage: `url(${bgImg})` }" />
- <!-- 顶部标题区域 -->
- <div class="header-section">
- <button class="logout-btn" @click="goHome">
- <i class="fas fa-home" />
- <span>主页</span>
- </button>
- <h1 class="page-title">借用</h1>
- <!-- 右侧操作按钮 -->
- <div class="header-actions">
- <button class="action-btn refresh-btn" @click="resetView">
- <i class="fas fa-sync-alt" />
- <span>重新校验</span>
- </button>
- </div>
- </div>
- <!-- 主内容区域 -->
- <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 }} 条数据,不识别 {{ unrecognizedCount }} 条</span>
- </div>
- <!-- 卡片网格区域 -->
- <div class="card-grid-wrapper">
- <!-- 空状态 -->
- <div v-if="materialList.length === 0 && !loading" class="empty-state">
- <i class="fas fa-inbox empty-icon" />
- <p>暂无数据</p>
- </div>
- <!-- 卡片网格 -->
- <div v-else class="card-grid">
- <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 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 v-if="item.selected" class="selected-indicator">
- <i class="fas fa-check" />
- </div> -->
- </div>
- </template>
- </div>
- </div>
- </main>
- <!-- 底部操作按钮 -->
- <div class="bottom-actions">
- <button class="submit-btn" @click="hasValidMaterials ? handleLeaveClick() : directExit()">
- {{ hasValidMaterials ? '闸机开门' : '直接出仓库' }}
- <span v-if="hasValidMaterials && selectedCount > 0">({{ selectedCount }})</span>
- </button>
- </div>
- <!-- Loading -->
- <div v-if="loading" class="loading-overlay">
- <div class="loading-dots">
- <div class="dot" />
- <div class="dot" />
- <div class="dot" />
- </div>
- <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>
- </template>
- <script setup>
- import { useRouter } from 'vue-router';
- import { ref, computed, onMounted, onUnmounted } from 'vue';
- import { showNotify } from 'vant';
- import { cfStockOut, createStockOut, cfStockOutLeave,leaveCFWarehouse } from '../api/stockOut.js';
- import { areArraysEqual } from '../common/utils.js';
- import { gateController } from '../hardware/GateOperate.js';
- // 图片资源
- import bgImg from '../assets/images/bj.png';
- // 路由
- const router = useRouter();
- // 操作的id
- const operationId = ref(null);
- // 返回主页
- const goHome = () => {
- router.push('/home');
- };
- // 表格加载状态
- const loading = ref(false);
- // 物料列表数据
- const materialList = ref([]);
- const epcs = ref([]);
- // 临时数组用于累积EPC数据
- const tempEpcs = ref([]);
- // 完成数量统计
- const completedCount = computed(() => {
- return materialList.value.filter(item => item.status === 1).length;
- });
- // 获取设备类型图标
- const getInventoryIcon = type => {
- const iconMap = {
- '工装': 'fas fa-cube',
- '设备': 'fas fa-cogs',
- '成品': 'fas fa-box',
- };
- return iconMap[type] || 'fas fa-cube';
- };
- // 获取状态颜色
- const getStatusColor = status => {
- const colorMap = {
- 1: '#10b981', // 完成 - 绿色
- 2: '#f59e0b', // 进行中 - 橙色
- 3: '#3b82f6', // 待开始 - 蓝色
- };
- return colorMap[status] || '#6b7280';
- };
- // 判断是否可以离开
- const isCanLeave = computed(() => {
- // 1. 先判断 materialList 是否存在且是数组
- if (!materialList.value || !Array.isArray(materialList.value)) {
- return false;
- }
- // 2. 判断是否有数据(空数组不能离开)
- if (materialList.value.length === 0) {
- return false;
- }
- // 3. 判断所有项的 status 是否都为 1
- // 使用 every 时需要确保 item 和 item.status 都存在
- return materialList.value.every(item => {
- return item && typeof item.status !== 'undefined' && item.status === 1;
- });
- });
- 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: '申请借用成功' });
- try {
- const res = await leaveCFWarehouse(record.inventoryId);
- if (res.errorCode === 0) {
- showNotify({ type: 'success', message: '申请借用成功' });
- operationId.value = record.inventoryId;
- 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调用失败' });
- } finally {
- loading.value = false;
- }
- };
- // 借用完成后离开
- const handleLeave = async () => {
- 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: '借用离开成功' });
- router.push('/');
- } else {
- showNotify({ type: 'danger', message: res.errorMessage });
- }
- } catch (error) {
- console.error('借用离开API调用失败:', error);
- showNotify({ type: 'danger', message: '借用离开API调用失败' });
- } finally {
- loading.value = false;
- }
- };
- const resetView = () => {
- materialList.value = [];
- };
- // 获取扫描到的借用数据
- const getStockOutList = async () => {
- // loading.value = true;
- const params = {
- 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) {
- 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 {
- showNotify({ type: 'danger', message: res.errorMessage });
- }
- } catch (error) {
- console.error('获取扫描到的借用数据API调用失败:', error);
- showNotify({ type: 'danger', message: '获取扫描到的借用数据API调用失败' });
- tempMaterialList.forEach(item => {
- item.queryStatus = 0;
- });
- } finally {
- loading.value = false;
- }
- };
- // 生成出库单
- const generateCFStockOut = async id => {
- loading.value = true;
- const params = [
- {
- stockOutPrepareLineId: id,
- deliveryMethod: 'Manual_Delivery',
- },
- ];
- try {
- const res = await createStockOut(params);
- if (res.errorCode === 0) {
- // getStockOutList();
- resetView();
- } else {
- showNotify({ type: 'danger', message: res.errorMessage });
- }
- } catch (error) {
- console.error('生成出库单API调用失败:', error);
- showNotify({ type: 'danger', message: '生成出库单API调用失败' });
- } finally {
- loading.value = false;
- }
- };
- let timer = null; // 用于保存当前定时器引用
- const addEpc = data => {
- const newEpcs = data.map(item => item.epc);
-
- // 将新的EPC数据添加到临时数组中,使用Set进行去重
- 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(() => {
- plugin.gateConfig.sendEpc = function(data){
- if (typeof(GATE_CONFIG) == 'undefined') {
- console.log('设备不支持读写器功能。');
- } else {
- addEpc(data);
- }
- };
- // 创建全局唯一定时器,每2秒执行一次
- timer = setInterval(() => {
- getStockOutList();
- // addEpc([ { 'epc': 'EEE000000640804317955613' }, { 'epc': 'FFF000000000000000000001' },{ 'epc': 'AAA000000000000000000002' }]);
- }, 1000);
- });
- onUnmounted(() => {
- plugin.gateConfig.sendEpc = null;
- // 清除定时器
- if (timer) {
- clearInterval(timer);
- timer = null;
- }
- });
- </script>
- <style scoped>
- /* ========== 基础样式 ========== */
- .stock-requisition-page {
- width: 100%;
- height: 100vh;
- max-height: 100vh;
- position: relative;
- font-family: 'Microsoft YaHei', sans-serif;
- color: #fff;
- overflow: hidden;
- display: flex;
- flex-direction: column;
- }
- /* 背景层 */
- .bg-layer {
- position: fixed;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- background-color: #041c3d;
- background-size: cover;
- background-position: center;
- background-repeat: no-repeat;
- z-index: 0;
- }
- /* ========== 主内容区域 ========== */
- .main-content {
- flex: 1;
- display: flex;
- flex-direction: column;
- padding: 0 30px;
- position: relative;
- z-index: 10;
- min-height: 0;
- overflow: hidden;
- }
- /* 统计信息 */
- .stats-section {
- background: rgba(9, 61, 140, 0.5);
- border: 1px solid #049FD8;
- border-radius: 12px;
- padding: 15px 20px;
- margin-bottom: 15px;
- flex-shrink: 0;
- }
- .stats-text {
- color: #7ec8ff;
- font-size: 16px;
- }
- /* ========== 卡片网格区域 ========== */
- .card-grid-wrapper {
- flex: 1;
- display: flex;
- flex-direction: column;
- min-height: 0;
- overflow-y: auto;
- overflow-x: hidden;
- padding-bottom: 10px;
- scrollbar-width: none;
- -ms-overflow-style: none;
- }
- .card-grid-wrapper::-webkit-scrollbar {
- display: none;
- }
- /* 空状态 */
- .empty-state {
- flex: 1;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- color: #7ec8ff;
- padding: 60px 0;
- }
- .empty-icon {
- font-size: 80px;
- margin-bottom: 20px;
- opacity: 0.5;
- }
- .empty-state p {
- font-size: 18px;
- margin: 0;
- }
- /* 卡片网格 - 4列布局 */
- .card-grid {
- display: grid;
- grid-template-columns: repeat(4, 1fr);
- gap: 20px;
- }
- /* ========== 设备卡片样式 ========== */
- .inventory-card {
- background: rgba(5, 30, 60, 0.8);
- border: 2px solid #0d4a8a;
- border-radius: 12px;
- overflow: hidden;
- transition: all 0.3s ease;
- position: relative;
- }
- .inventory-card:hover {
- border-color: #1e90ff;
- box-shadow: 0 0 20px rgba(30, 144, 255, 0.3);
- transform: translateY(-3px);
- }
- .inventory-card.completed {
- border-color: #10b981;
- 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;
- top: 10px;
- left: 10px;
- width: 36px;
- height: 36px;
- background: linear-gradient(135deg, #1e90ff 0%, #00bfff 100%);
- border-radius: 50%;
- display: flex;
- align-items: center;
- justify-content: center;
- font-size: 16px;
- font-weight: bold;
- color: #fff;
- z-index: 2;
- box-shadow: 0 2px 8px rgba(0, 191, 255, 0.4);
- }
- .card-index.completed {
- /* background: linear-gradient(135deg, #10b981 0%, #34d399 100%); */
- box-shadow: 0 2px 8px rgba(16, 185, 129, 0.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;
- flex-direction: column;
- gap: 8px;
- padding: 8px 0;
- min-height: 48px; /* 确保与按钮区域高度一致 */
- }
- .borrower-row {
- display: flex;
- align-items: center;
- 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;
- flex: 1;
- }
- /* 信息区域 */
- .card-info {
- padding: 50px 15px 15px;
- }
- .info-row {
- display: flex;
- 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 {
- border-bottom: none; /* 最后一行不显示分割线 */
- }
- .info-label {
- color: #7ec8ff;
- white-space: nowrap;
- margin-right: 5px;
- }
- .info-value {
- color: #fff;
- flex: 1;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
- /* 位置行样式 */
- .location-row {
- display: flex;
- align-items: center;
- margin-top: 4px;
- /* 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 {
- color: #00bfff;
- font-size: 12px;
- margin-right: 6px;
- }
- /* ========== 操作区域(固定高度) ========== */
- .card-action-section {
- padding: 8px 15px;
- min-height: 48px;
- display: flex;
- align-items: center;
- justify-content: center;
- /* 移除边框和背景色差异,与无需操作区域保持一致 */
- }
- .status-placeholder {
- color: #5a8abf;
- font-size: 14px;
- opacity: 0.8;
- margin-top: -10px;
- }
- /* 状态按钮 */
- .status-btn {
- width: 100%;
- padding: 10px 15px;
- border-radius: 6px;
- font-size: 13px;
- font-weight: 500;
- cursor: pointer;
- transition: all 0.3s;
- border: none;
- display: flex;
- align-items: center;
- justify-content: center;
- gap: 6px;
- }
- .completed-btn {
- background: linear-gradient(90deg, #10b981 0%, #34d399 100%);
- color: #fff;
- opacity: 0.7;
- cursor: not-allowed;
- }
- .start-btn {
- background: linear-gradient(90deg, #f59e0b 0%, #fbbf24 100%);
- color: #fff;
- }
- .start-btn:hover {
- box-shadow: 0 0 15px rgba(245, 158, 11, 0.5);
- }
- .apply-btn {
- background: linear-gradient(90deg, #1e90ff 0%, #00bfff 100%);
- color: #fff;
- }
- .apply-btn:hover {
- 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%;
- padding: 15px 30px;
- box-sizing: border-box;
- background: rgba(4, 28, 61, 0.95);
- z-index: 20;
- flex-shrink: 0;
- }
- .submit-btn {
- width: 100%;
- padding: 18px 0;
- background: #4a99e2;
- border: none;
- border-radius: 12px;
- font-size: 24px;
- font-weight: bold;
- color: #fff;
- cursor: pointer;
- transition: all 0.3s;
- letter-spacing: 8px;
- text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
- }
- .submit-btn:hover:not(:disabled) {
- box-shadow: 0 0 30px rgba(16, 185, 129, 0.6);
- transform: translateY(-2px);
- }
- .submit-btn:disabled {
- opacity: 0.5;
- cursor: not-allowed;
- background: linear-gradient(90deg, #6b7280 0%, #9ca3af 100%);
- }
- /* ========== 响应式 - 横屏 ========== */
- @media screen and (orientation: landscape) {
- .header-section {
- padding: 30px 20px 10px 20px;
- }
- .page-title {
- font-size: 22px;
- }
- .logout-btn {
- padding: 6px 14px;
- font-size: 13px;
- left: 20px;
- }
- .logout-btn i {
- font-size: 14px;
- }
- .header-actions {
- right: 20px;
- }
- .action-btn {
- padding: 6px 14px;
- font-size: 13px;
- }
- .action-btn i {
- font-size: 14px;
- }
- .main-content {
- padding: 0 20px;
- }
- .stats-section {
- padding: 10px 15px;
- margin-bottom: 10px;
- }
- .stats-text {
- font-size: 14px;
- }
- /* 卡片网格响应式 */
- .card-grid {
- grid-template-columns: repeat(6, 1fr);
- gap: 15px;
- }
- .card-index {
- width: 24px;
- height: 24px;
- font-size: 11px;
- top: 6px;
- left: 6px;
- }
- .card-image {
- margin: 10px;
- margin-bottom: 8px;
- width: calc(100% - 20px);
- }
- .image-placeholder {
- font-size: 36px;
- }
- .card-info {
- padding: 32px 10px 8px;
- }
- .info-row {
- font-size: 11px;
- margin-bottom: 3px;
- }
- .location-icon {
- font-size: 10px;
- }
- .card-action-section {
- padding: 8px 10px;
- min-height: 40px;
- }
- .status-btn {
- padding: 10px;
- font-size: 11px;
- gap: 4px;
- }
- .status-placeholder {
- font-size: 14px;
- }
- .bottom-actions {
- padding: 10px 20px;
- }
- .submit-btn {
- padding: 12px 0;
- font-size: 18px;
- letter-spacing: 6px;
- border-radius: 8px;
- }
- }
- </style>
|