InConfirm.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814
  1. <!-- 还料入库 - 智能仓储风格 -->
  2. <template>
  3. <div class="stock-requisition-page">
  4. <!-- 背景层 -->
  5. <div class="bg-layer" :style="{ backgroundImage: `url(${bgImg})` }" />
  6. <!-- 顶部标题区域 -->
  7. <div class="header-section">
  8. <button class="logout-btn" @click="goHome">
  9. <i class="fas fa-home" />
  10. <span>主页</span>
  11. </button>
  12. <h1 class="page-title">入库</h1>
  13. <!-- 右侧操作按钮 -->
  14. <div class="header-actions">
  15. <button class="action-btn refresh-btn" @click="resetView">
  16. <i class="fas fa-sync-alt" />
  17. <span>重新校验</span>
  18. </button>
  19. </div>
  20. </div>
  21. <!-- 主内容区域 -->
  22. <main class="main-content">
  23. <!-- 统计信息 -->
  24. <div v-if="materialList.length > 0" class="stats-section">
  25. <span class="stats-text">共 {{ materialList.length }} 条数据,不识别 {{ unrecognizedCount }} 条</span>
  26. </div>
  27. <!-- 卡片网格区域 -->
  28. <div class="card-grid-wrapper">
  29. <!-- 空状态 -->
  30. <div v-if="materialList.length === 0 && !loading" class="empty-state">
  31. <i class="fas fa-inbox empty-icon" />
  32. <p>暂无数据</p>
  33. </div>
  34. <!-- 卡片网格 -->
  35. <div v-else class="card-grid">
  36. <template v-for="(item, index) in materialList" :key="item.id || index">
  37. <div
  38. v-if="item.inventoryId != null"
  39. class="inventory-card"
  40. :class="getCardClass(item.remarks)"
  41. @click="handleSelect(item)"
  42. >
  43. <!-- 卡片序号 -->
  44. <div
  45. v-if="item.selected" class="card-index"
  46. style="background: linear-gradient(135deg, #a8f63b 0%, #60faee 100%);"
  47. :class="getCardClass(item.remarks)"
  48. />
  49. <!-- 图片区域 -->
  50. <div class="card-image">
  51. <div class="image-placeholder" :class="getCardClass(item.remarks)">
  52. <i :class="getInventoryIcon(item.inventoryType)" />
  53. </div>
  54. </div>
  55. <!-- 信息区域 -->
  56. <div class="card-info">
  57. <div class="info-row">
  58. <span class="info-label">名称:</span>
  59. <span class="info-value">{{ item.inventoryName || '-' }}</span>
  60. </div>
  61. <div class="info-row">
  62. <span class="info-label">编号:</span>
  63. <span class="info-value">{{ item.inventoryNo || '-' }}</span>
  64. </div>
  65. <div class="info-row location-row">
  66. <i class="fas fa-map-marker-alt location-icon" />
  67. <span class="info-value">{{ item.positionName || '-' }} / {{ item.warehouseName || '-' }}</span>
  68. </div>
  69. </div>
  70. <!-- 状态区域(固定高度) -->
  71. <div class="card-status-section">
  72. <div class="status-badge" :class="getCardClass(item.remarks)">
  73. <i class="fas fa-exclamation-circle" />
  74. {{ item.remarks || '-' }}
  75. </div>
  76. </div>
  77. </div>
  78. </template>
  79. </div>
  80. </div>
  81. </main>
  82. <!-- 底部操作按钮 -->
  83. <div class="bottom-actions">
  84. <button class="submit-btn" @click="handleComplete">
  85. 确认入库
  86. <span v-if="validStockCount != 0">{{ validStockCount }}</span>
  87. </button>
  88. </div>
  89. <!-- Loading -->
  90. <div v-if="loading" class="loading-overlay">
  91. <div class="loading-dots">
  92. <div class="dot" />
  93. <div class="dot" />
  94. <div class="dot" />
  95. </div>
  96. <span class="loading-text">加载中...</span>
  97. </div>
  98. </div>
  99. <!-- 直接进入仓库提示 -->
  100. <div v-if="enterConfirmVisible" class="tech-modal-overlay" @click.self="enterConfirmVisible = false">
  101. <div class="tech-modal">
  102. <div class="modal-content-row">
  103. <div class="modal-text">
  104. <h3>请确认您要直接进入仓库</h3>
  105. <p>系统检测到您未携带物料,或者未勾选任何物料,是否确认直接进入仓库?</p>
  106. </div>
  107. <div class="modal-icon">
  108. <div class="icon-box">
  109. <i class="fas fa-clipboard-check" />
  110. </div>
  111. </div>
  112. </div>
  113. <div class="modal-footer">
  114. <button class="modal-btn cancel-btn" @click="enterConfirm">直接进入仓库</button>
  115. <button class="modal-btn confirm-btn" @click="enterConfirmVisible = false">取消</button>
  116. </div>
  117. </div>
  118. </div>
  119. </template>
  120. <script setup>
  121. import { useRouter } from 'vue-router';
  122. import { showNotify } from 'vant';
  123. import { ref,reactive, onMounted, computed, onUnmounted } from 'vue';
  124. import { cfStockIn, createStockIn } from '../api/stockIn.js';
  125. import { areArraysEqual } from '../common/utils.js';
  126. import { gateController } from '../hardware/GateOperate.js';
  127. // 图片资源
  128. import bgImg from '../assets/images/bj.png';
  129. const router = useRouter();
  130. // 返回主页
  131. const goHome = () => {
  132. router.push('/home');
  133. };
  134. // 表格加载状态
  135. const loading = ref(false);
  136. // 物料列表数据
  137. const materialList = ref([]);
  138. const epcs = ref([]);
  139. // 分页配置
  140. const pagination = reactive({
  141. start: 1,
  142. lang: 10,
  143. total: 0,
  144. });
  145. // 计算不在库的数量
  146. const validStockCount = computed(() => {
  147. return materialList.value.filter(item => item.remarks === '不在库' && item.selected === true).length;
  148. });
  149. // 根据 remarks 返回卡片样式类
  150. const getCardClass = remarks => {
  151. if (remarks === '不在库') {
  152. return 'not-in-stock-card';
  153. } else if (remarks === '在库') {
  154. return 'in-stock-card';
  155. }
  156. return '';
  157. };
  158. // 获取设备类型图标
  159. const getInventoryIcon = type => {
  160. const iconMap = {
  161. '工装': 'fas fa-cube',
  162. '设备': 'fas fa-cogs',
  163. '成品': 'fas fa-box',
  164. };
  165. return iconMap[type] || 'fas fa-cube';
  166. };
  167. // 获取状态颜色
  168. // const getStatusColor = remarks => {
  169. // if (remarks === '不在库') {
  170. // return '#3b82f6'; // 蓝色 - 需要入库
  171. // } else if (remarks === '在库') {
  172. // return '#10b981'; // 绿色 - 已在库
  173. // }
  174. // return '#6b7280'; // 灰色 - 默认
  175. // };
  176. // 还料入库
  177. const handleComplete = async () => {
  178. // 只处理不在库的数据
  179. const notInStockItems = materialList.value.filter(item => item.selected === true);
  180. if (notInStockItems.length === 0) {
  181. enterConfirmVisible.value = true;
  182. return;
  183. }
  184. const params = [];
  185. materialList.value.forEach(item => {
  186. if (item.selected === true) {
  187. params.push({
  188. inventoryId: item.inventoryId,
  189. });
  190. }
  191. });
  192. console.log('提交参数:', params);
  193. await generateCFStockIn(params);
  194. };
  195. // 校验
  196. const resetView = () => {
  197. epcs.value = [];
  198. materialList.value = [];
  199. };
  200. // 获取物料列表(外侧校验)
  201. const getList = async () => {
  202. // loading.value = true;
  203. const params = {
  204. epcList: [],
  205. };
  206. const tempMaterialList = [];
  207. for(let i = 0; i < materialList.value.length; i++) {
  208. if(materialList.value[i].queryStatus === 0) {
  209. params.epcList.push(materialList.value[i].epc);
  210. materialList.value[i].queryStatus = 1;
  211. tempMaterialList.push(materialList.value[i]);
  212. }
  213. }
  214. if(params.epcList.length == 0){
  215. return;
  216. }
  217. try {
  218. const res = await cfStockIn(params);
  219. if (res.errorCode === 0) {
  220. if (res.datas && res.datas.length > 0) {
  221. res.datas.forEach(i => {
  222. materialList.value.forEach(j => {
  223. if (j.epc === i.epc) {
  224. j.inventoryName = i.inventoryName;
  225. j.inventoryNo = i.inventoryNo;
  226. j.inventoryType = i.inventoryType;
  227. j.warehouseName = i.warehouseName;
  228. j.positionName = i.positionName;
  229. j.inventoryId = i.inventoryId;
  230. j.queryStatus = 2;
  231. j.selected = false;
  232. j.remarks = i.remarks;
  233. }
  234. });
  235. });
  236. pagination.total = materialList.value.length;
  237. } else {
  238. materialList.value = [];
  239. }
  240. } else {
  241. materialList.value = [];
  242. showNotify({ type: 'danger', message: res.errorMessage });
  243. }
  244. } catch (error) {
  245. console.error('获取物料列表API调用失败:', error);
  246. showNotify({ type: 'danger', message: '获取物料列表API调用失败' });
  247. // 处理查询失败的物料
  248. tempMaterialList.forEach(item => {
  249. item.queryStatus = 0;
  250. });
  251. } finally {
  252. loading.value = false;
  253. }
  254. };
  255. // 生成CF入库单
  256. const generateCFStockIn = async params => {
  257. loading.value = true;
  258. try {
  259. const res = await createStockIn(params);
  260. if (res.errorCode === 0) {
  261. // 调用开门操作
  262. gateController('SHOTOPEN');
  263. showNotify({ type: 'success', message: '入库申请已完成,还料任务已创建!' });
  264. // 跳转回主页
  265. router.push('/');
  266. } else {
  267. showNotify({ type: 'danger', message: res.errorMessage });
  268. }
  269. } catch (error) {
  270. console.error('生成CF入库单API调用失败:', error);
  271. showNotify({ type: 'danger', message: '生成CF入库单API调用失败' });
  272. } finally {
  273. loading.value = false;
  274. }
  275. };
  276. let timer = null; // 用于保存当前定时器引用
  277. const addEpc = data => {
  278. const newEpcs = data.map(item => item.epc);
  279. // 将新epc添加到临时数组中(使用Set去重)
  280. const uniqueEpcs = new Set([...newEpcs]);
  281. if(newEpcs != null && newEpcs.length > 0) {
  282. newEpcs.forEach(item => {
  283. let exist = false;
  284. for(let i =0; i < materialList.value.length; i++) {
  285. if(materialList.value[i].epc === item) {
  286. exist = true;
  287. break;
  288. }
  289. }
  290. if(exist == false) {
  291. materialList.value.push({
  292. epc: item,
  293. queryStatus: 0, // 0: 未查询, 1: 查询中, 2: 已查询, 3: 未查询到
  294. });
  295. }
  296. });
  297. }
  298. };
  299. onMounted(() => {
  300. // getList();
  301. plugin.gateConfig.sendEpc = function(data){
  302. if (typeof(GATE_CONFIG) == 'undefined') {
  303. console.log('设备不支持读写器功能。');
  304. } else {
  305. addEpc(data);
  306. }
  307. };
  308. // 创建全局唯一定时器,每2秒执行一次getList
  309. timer = setInterval(() => {
  310. // 只有当临时数组有数据时才执行getList
  311. // 将临时数组的数据赋值给epcs
  312. // 执行获取列表
  313. //addEpc([{
  314. // 'epc': 'FFF000000000000000000001',
  315. // 'epc': 'AAA000000000000000000002',
  316. //}]);
  317. getList();
  318. }, 1000);
  319. });
  320. onUnmounted(() => {
  321. plugin.gateConfig.sendEpc = null;
  322. // 清除定时器
  323. if (timer) {
  324. clearInterval(timer);
  325. timer = null;
  326. }
  327. });
  328. // 不识别的数据统计
  329. const unrecognizedCount = computed(() => {
  330. return materialList.value.filter(item => item.inventoryId == null).length;
  331. });
  332. const handleSelect = item => {
  333. if(item.remarks === '不在库'){
  334. item.selected = !item.selected;
  335. }
  336. };
  337. const enterConfirmVisible = ref(false);
  338. const enterConfirm = () => {
  339. enterConfirmVisible.value = false;
  340. // 调用开门操作
  341. gateController('SHOTOPEN');
  342. // 跳转回主页
  343. router.push('/');
  344. };
  345. </script>
  346. <style scoped>
  347. /* ========== 基础样式 ========== */
  348. .stock-requisition-page {
  349. width: 100%;
  350. height: 100vh;
  351. max-height: 100vh;
  352. position: relative;
  353. font-family: 'Microsoft YaHei', sans-serif;
  354. color: #fff;
  355. overflow: hidden;
  356. display: flex;
  357. flex-direction: column;
  358. }
  359. /* 背景层 */
  360. .bg-layer {
  361. position: fixed;
  362. top: 0;
  363. left: 0;
  364. width: 100%;
  365. height: 100%;
  366. background-color: #041c3d;
  367. background-size: cover;
  368. background-position: center;
  369. background-repeat: no-repeat;
  370. z-index: 0;
  371. }
  372. /* ========== 主内容区域 ========== */
  373. .main-content {
  374. flex: 1;
  375. display: flex;
  376. flex-direction: column;
  377. padding: 0 30px;
  378. position: relative;
  379. z-index: 10;
  380. min-height: 0;
  381. overflow: hidden;
  382. }
  383. /* 统计信息 */
  384. .stats-section {
  385. background: rgba(9, 61, 140, 0.5);
  386. border: 1px solid #049FD8;
  387. border-radius: 12px;
  388. padding: 15px 20px;
  389. margin-bottom: 15px;
  390. flex-shrink: 0;
  391. }
  392. .stats-text {
  393. color: #7ec8ff;
  394. font-size: 16px;
  395. }
  396. /* ========== 卡片网格区域 ========== */
  397. .card-grid-wrapper {
  398. flex: 1;
  399. display: flex;
  400. flex-direction: column;
  401. min-height: 0;
  402. overflow-y: auto;
  403. overflow-x: hidden;
  404. padding-bottom: 10px;
  405. scrollbar-width: none;
  406. -ms-overflow-style: none;
  407. }
  408. .card-grid-wrapper::-webkit-scrollbar {
  409. display: none;
  410. }
  411. /* 空状态 */
  412. .empty-state {
  413. flex: 1;
  414. display: flex;
  415. flex-direction: column;
  416. align-items: center;
  417. justify-content: center;
  418. color: #7ec8ff;
  419. padding: 60px 0;
  420. }
  421. .empty-icon {
  422. font-size: 80px;
  423. margin-bottom: 20px;
  424. opacity: 0.5;
  425. }
  426. .empty-state p {
  427. font-size: 18px;
  428. margin: 0;
  429. }
  430. /* 卡片网格 - 4列布局 */
  431. .card-grid {
  432. display: grid;
  433. grid-template-columns: repeat(4, 1fr);
  434. gap: 20px;
  435. }
  436. /* ========== 设备卡片样式 ========== */
  437. .inventory-card {
  438. background: rgba(5, 30, 60, 0.8);
  439. border: 2px solid #0d4a8a;
  440. border-radius: 12px;
  441. overflow: hidden;
  442. transition: all 0.3s ease;
  443. position: relative;
  444. }
  445. .inventory-card:hover {
  446. border-color: #1e90ff;
  447. box-shadow: 0 0 20px rgba(30, 144, 255, 0.3);
  448. transform: translateY(-3px);
  449. }
  450. /* 不在库卡片 - 蓝色(需入库) */
  451. .inventory-card.not-in-stock-card {
  452. border-color: #3b82f6;
  453. }
  454. /* 在库卡片 - 红色警告 */
  455. .inventory-card.in-stock-card {
  456. border-color: #ef4444;
  457. }
  458. /* 卡片序号 - 左上角 */
  459. .card-index {
  460. position: absolute;
  461. top: 10px;
  462. left: 10px;
  463. width: 36px;
  464. height: 36px;
  465. /* background: linear-gradient(135deg, #1e90ff 0%, #00bfff 100%); */
  466. background: linear-gradient(135deg, rgb(86, 236, 17) 0%, #28ea0a 100%);
  467. border-radius: 50%;
  468. display: flex;
  469. align-items: center;
  470. justify-content: center;
  471. font-size: 16px;
  472. font-weight: bold;
  473. color: #fff;
  474. z-index: 2;
  475. box-shadow: 0 2px 8px rgba(0, 191, 255, 0.4);
  476. }
  477. .card-index.not-in-stock-card {
  478. background: linear-gradient(135deg, #3b82f6 0%, #60a5fa 100%);
  479. box-shadow: 0 2px 8px rgba(59, 130, 246, 0.4);
  480. }
  481. .card-index.in-stock-card {
  482. background: linear-gradient(135deg, #ef4444 0%, #f87171 100%);
  483. box-shadow: 0 2px 8px rgba(239, 68, 68, 0.4);
  484. }
  485. /* 图片区域 */
  486. .card-image {
  487. width: 100%;
  488. aspect-ratio: 3 / 4;
  489. display: flex;
  490. align-items: center;
  491. justify-content: center;
  492. overflow: hidden;
  493. margin: 15px;
  494. margin-bottom: 10px;
  495. border-radius: 8px;
  496. width: calc(100% - 30px);
  497. }
  498. .image-placeholder {
  499. display: flex;
  500. align-items: center;
  501. justify-content: center;
  502. width: 100%;
  503. height: 100%;
  504. background: linear-gradient(135deg, #f0f4f8 0%, #e8ecf0 100%);
  505. color: #94a3b8;
  506. font-size: 48px;
  507. }
  508. .image-placeholder.not-in-stock-card {
  509. background: linear-gradient(135deg, #3b82f6 0%, #60a5fa 100%);
  510. color: #fff;
  511. }
  512. .image-placeholder.in-stock-card {
  513. background: linear-gradient(135deg, #ef4444 0%, #f87171 100%);
  514. color: #fff;
  515. }
  516. /* 信息区域 */
  517. .card-info {
  518. padding: 10px 15px 15px;
  519. }
  520. .info-row {
  521. display: flex;
  522. align-items: baseline;
  523. margin-bottom: 6px;
  524. font-size: 14px;
  525. }
  526. .info-row:last-child {
  527. margin-bottom: 0;
  528. }
  529. .info-label {
  530. color: #7ec8ff;
  531. white-space: nowrap;
  532. margin-right: 5px;
  533. }
  534. .info-value {
  535. color: #fff;
  536. flex: 1;
  537. overflow: hidden;
  538. text-overflow: ellipsis;
  539. white-space: nowrap;
  540. }
  541. /* 位置行样式 */
  542. .location-row {
  543. display: flex;
  544. align-items: center;
  545. margin-top: 4px;
  546. padding-top: 4px;
  547. border-top: 1px solid rgba(30, 144, 255, 0.2);
  548. }
  549. .location-icon {
  550. color: #00bfff;
  551. font-size: 12px;
  552. margin-right: 6px;
  553. }
  554. /* ========== 状态区域(固定高度) ========== */
  555. .card-status-section {
  556. padding: 12px 15px;
  557. border-top: 1px solid rgba(30, 144, 255, 0.3);
  558. background: rgba(9, 61, 140, 0.3);
  559. min-height: 50px;
  560. display: flex;
  561. align-items: center;
  562. justify-content: center;
  563. }
  564. /* 状态标签 */
  565. .status-badge {
  566. padding: 8px 20px;
  567. border-radius: 20px;
  568. font-size: 13px;
  569. font-weight: 500;
  570. display: flex;
  571. align-items: center;
  572. gap: 6px;
  573. }
  574. .status-badge.not-in-stock-card {
  575. background: rgba(59, 130, 246, 0.3);
  576. border: 1px solid #3b82f6;
  577. color: #93c5fd;
  578. }
  579. .status-badge.in-stock-card {
  580. background: rgba(239, 68, 68, 0.3);
  581. border: 1px solid #ef4444;
  582. color: #fca5a5;
  583. }
  584. /* ========== 底部操作按钮 ========== */
  585. .bottom-actions {
  586. width: 100%;
  587. padding: 15px 30px;
  588. box-sizing: border-box;
  589. background: rgba(4, 28, 61, 0.95);
  590. z-index: 20;
  591. flex-shrink: 0;
  592. }
  593. .submit-btn {
  594. width: 100%;
  595. padding: 18px 0;
  596. background: #4a99e2;
  597. border: none;
  598. border-radius: 12px;
  599. font-size: 24px;
  600. font-weight: bold;
  601. color: #fff;
  602. cursor: pointer;
  603. transition: all 0.3s;
  604. letter-spacing: 8px;
  605. text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
  606. }
  607. .submit-btn:hover:not(:disabled) {
  608. box-shadow: 0 0 30px rgba(16, 185, 129, 0.6);
  609. transform: translateY(-2px);
  610. }
  611. .submit-btn:disabled {
  612. opacity: 0.5;
  613. cursor: not-allowed;
  614. background: linear-gradient(90deg, #6b7280 0%, #9ca3af 100%);
  615. }
  616. /* ========== 响应式 - 横屏 ========== */
  617. @media screen and (orientation: landscape) {
  618. .header-section {
  619. padding: 10px 20px;
  620. }
  621. .page-title {
  622. font-size: 22px;
  623. }
  624. .logout-btn {
  625. padding: 6px 14px;
  626. font-size: 13px;
  627. left: 20px;
  628. }
  629. .logout-btn i {
  630. font-size: 14px;
  631. }
  632. .header-actions {
  633. right: 20px;
  634. }
  635. .action-btn {
  636. padding: 6px 14px;
  637. font-size: 13px;
  638. }
  639. .action-btn i {
  640. font-size: 14px;
  641. }
  642. .main-content {
  643. padding: 0 20px;
  644. }
  645. .stats-section {
  646. padding: 10px 15px;
  647. margin-bottom: 10px;
  648. }
  649. .stats-text {
  650. font-size: 14px;
  651. }
  652. /* 卡片网格响应式 */
  653. .card-grid {
  654. grid-template-columns: repeat(6, 1fr);
  655. gap: 15px;
  656. }
  657. .card-index {
  658. width: 24px;
  659. height: 24px;
  660. font-size: 11px;
  661. top: 6px;
  662. left: 6px;
  663. }
  664. .card-image {
  665. margin: 10px;
  666. margin-bottom: 8px;
  667. width: calc(100% - 20px);
  668. }
  669. .image-placeholder {
  670. font-size: 36px;
  671. }
  672. .card-info {
  673. padding: 6px 10px 8px;
  674. }
  675. .info-row {
  676. font-size: 11px;
  677. margin-bottom: 3px;
  678. }
  679. .location-icon {
  680. font-size: 10px;
  681. }
  682. .card-status-section {
  683. padding: 8px 10px;
  684. min-height: 40px;
  685. }
  686. .status-badge {
  687. padding: 5px 12px;
  688. font-size: 11px;
  689. gap: 4px;
  690. }
  691. .bottom-actions {
  692. padding: 10px 20px;
  693. }
  694. .submit-btn {
  695. padding: 12px 0;
  696. font-size: 18px;
  697. letter-spacing: 6px;
  698. border-radius: 8px;
  699. }
  700. }
  701. </style>