Browse Source

init

master
han\hanst 1 year ago
parent
commit
57546bd2ba
  1. 41
      src/api/label-split-merge/label-split-merge.js
  2. 37
      src/api/other-inbound/other-inbound.js
  3. 29
      src/api/property-change/property-change.js
  4. 138
      src/router/index.js
  5. 4
      src/views/main.vue
  6. 629
      src/views/modules/label-split-merge/labelSplitMerge.vue
  7. 1327
      src/views/modules/other-inout/otherInboundDetail.vue
  8. 400
      src/views/modules/other-inout/otherInboundList.vue
  9. 2
      src/views/modules/other-inout/otherOutboundDetail.vue
  10. 2
      src/views/modules/production-pick/productionPicking.vue
  11. 4
      src/views/modules/production-pick/productionPickingDetail.vue
  12. 4
      src/views/modules/production/productionInboundStorage.vue
  13. 486
      src/views/modules/property-change/propertyChange.vue
  14. 4
      src/views/modules/purchase-inbound/inboundStorage.vue
  15. 2
      src/views/modules/purchase-return/purchaseReturnDetail.vue
  16. 2
      src/views/modules/sales-return/salesReturnStorage.vue
  17. 8
      src/views/modules/sales/salesOutboundDetail.vue

41
src/api/label-split-merge/label-split-merge.js

@ -0,0 +1,41 @@
import { createAPI } from "@/utils/httpRequest.js";
/**
* 根据标签条码获取库存信息
* @param {Object} data - 查询参数
* @param {string} data.labelCode - 标签条码
* @param {string} data.site - 站点
* @param {string} data.warehouseId - 仓库ID
*/
export const getStockInfoByLabelCode = data => createAPI(`label-split-merge/stock-info`, 'post', data)
/**
* 标签拆分
* @param {Object} data - 拆分数据
* @param {string} data.originalLabelCode - 原标签条码
* @param {string} data.site - 站点
* @param {string} data.warehouseId - 仓库ID
* @param {string} data.buNo - 业务单元
* @param {string} data.partNo - 物料编码
* @param {string} data.batchNo - 批次号
* @param {string} data.locationId - 库位
* @param {number} data.originalQuantity - 原数量
* @param {number} data.splitQuantity - 拆分数量
*/
export const splitLabel = data => createAPI(`label-split-merge/split`, 'post', data)
/**
* 标签合并
* @param {Object} data - 合并数据
* @param {string} data.targetLabelCode - 目标标签条码
* @param {string} data.sourceLabelCode - 源标签条码
* @param {string} data.site - 站点
* @param {string} data.warehouseId - 仓库ID
* @param {string} data.buNo - 业务单元
* @param {string} data.partNo - 物料编码
* @param {string} data.batchNo - 批次号
* @param {string} data.locationId - 库位
* @param {number} data.targetQuantity - 目标标签数量
* @param {number} data.sourceQuantity - 源标签数量
*/
export const mergeLabel = data => createAPI(`label-split-merge/merge`, 'post', data)

37
src/api/other-inbound/other-inbound.js

@ -0,0 +1,37 @@
import { createAPI } from "@/utils/httpRequest.js";
/**
* 获取其它入库单列表
* @param {Object} data - 查询参数
*/
export const getOtherInboundList = data => createAPI(`otherInbound/getInboundList`, 'post', data)
/**
* 获取其它入库单详情
* @param {Object} data - 查询参数
*/
export const getOtherInboundDetails = data => createAPI(`otherInbound/getInboundDetails`, 'post', data)
/**
* 验证物料与其它入库单是否匹配
* @param {Object} data - 验证参数
*/
export const validateMaterialWithInbound = data => createAPI(`otherInbound/validateMaterialWithInbound`, 'post', data)
/**
* 确认其它入库
* @param {Object} data - 入库数据
*/
export const confirmOtherInbound = data => createAPI(`otherInbound/confirmOtherInbound`, 'post', data)
/**
* 获取其它入库单物料清单
* @param {Object} data - 查询参数 {site, buNo, inboundNo}
*/
export const getMaterialList = data => createAPI(`otherInbound/getMaterialList`, 'post', data)
/**
* 添加物料到入库单
* @param {Object} data - 添加物料参数 {site, buNo, inboundNo, materialCode, actualQty, warehouseId}
*/
export const addMaterialToInbound = data => createAPI(`otherInbound/addMaterialToInbound`, 'post', data)

29
src/api/property-change/property-change.js

@ -0,0 +1,29 @@
import { createAPI } from "@/utils/httpRequest.js";
/**
* 根据标签条码获取库存信息
* @param {Object} data - 查询参数
* @param {string} data.labelCode - 标签条码
* @param {string} data.site - 站点
* @param {string} data.warehouseId - 仓库ID
*/
export const getStockInfoByLabelCode = data => createAPI(`property-change/stock-info`, 'post', data)
/**
* 保存属性变动
* @param {Object} data - 变动数据
* @param {string} data.labelCode - 标签条码
* @param {string} data.site - 站点
* @param {string} data.warehouseId - 仓库ID
* @param {string} data.buNo - 业务单元
* @param {string} data.partNo - 物料编码
* @param {string} data.batchNo - 批次号
* @param {string} data.oldLocationId - 原库位
* @param {string} data.newLocationId - 新库位
* @param {string} data.oldProductionDate - 原生产日期
* @param {string} data.newProductionDate - 新生产日期
* @param {string} data.oldExpiryDate - 原有效期
* @param {string} data.newExpiryDate - 新有效期
* @param {number} data.quantity - 数量
*/
export const savePropertyChange = data => createAPI(`property-change/save`, 'post', data)

138
src/router/index.js

@ -23,58 +23,110 @@ const globalRoutes = [
{ path: '/404', component: _import('common/404'), name: '404', meta: { title: '404未找到' } },
{ path: '/login', component: _import('common/login'), name: 'login', meta: { title: '登录' } },
// 采购入库
{path: "/purchaseInbound",name: "porecv", component: resolve => require(["@/views/modules/purchase-inbound/purchase-inbound.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
{path: "/recv",name: "recv", component: resolve => require(["@/views/modules/purchase-inbound/purchase-inbound.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
{path: "/qualifiedStorage",name: "qualifiedStorage", component: resolve => require(["@/views/modules/purchase-inbound/qualifiedStorage.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
{ path: "/purchaseInbound", name: "porecv", component: resolve => require(["@/views/modules/purchase-inbound/purchase-inbound.vue"], resolve), meta: { transition: 'instant', preload: true, keepAlive: true } },
{ path: "/recv", name: "recv", component: resolve => require(["@/views/modules/purchase-inbound/purchase-inbound.vue"], resolve), meta: { transition: 'instant', preload: true, keepAlive: true } },
{ path: "/qualifiedStorage", name: "qualifiedStorage", component: resolve => require(["@/views/modules/purchase-inbound/qualifiedStorage.vue"], resolve), meta: { transition: 'instant', preload: true, keepAlive: true } },
// 入库上架页面
{path: "/inboundStorage/:buNo/:inboundNo",name: "inboundStorage",
component: resolve => require(["@/views/modules/purchase-inbound/inboundStorage.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
{
path: "/inboundStorage/:buNo/:inboundNo", name: "inboundStorage",
component: resolve => require(["@/views/modules/purchase-inbound/inboundStorage.vue"], resolve), meta: { transition: 'instant', preload: true, keepAlive: true }
},
// 销售退货
{path: "/salesReturn",name: "salesReturn", component: resolve => require(["@/views/modules/sales-return/sales-return.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
{path: "/salesReturnList",name: "salesReturnList", component: resolve => require(["@/views/modules/sales-return/salesReturnList.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
{path: "/salesReturnStorage/:returnNo/:partNo/:buNo",name: "SalesReturnStorage",
component: resolve => require(["@/views/modules/sales-return/salesReturnStorage.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
{ path: "/salesReturn", name: "salesReturn", component: resolve => require(["@/views/modules/sales-return/sales-return.vue"], resolve), meta: { transition: 'instant', preload: true, keepAlive: true } },
{ path: "/salesReturnList", name: "salesReturnList", component: resolve => require(["@/views/modules/sales-return/salesReturnList.vue"], resolve), meta: { transition: 'instant', preload: true, keepAlive: true } },
{
path: "/salesReturnStorage/:returnNo/:partNo/:buNo", name: "SalesReturnStorage",
component: resolve => require(["@/views/modules/sales-return/salesReturnStorage.vue"], resolve), meta: { transition: 'instant', preload: true, keepAlive: true }
},
// 生产发料
{path: "/productionissue",name: "productionissue", component: resolve => require(["@/views/modules/production-issue/productionIssuePda.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
// 生产发料
{ path: "/productionissue", name: "productionissue", component: resolve => require(["@/views/modules/production-issue/productionIssuePda.vue"], resolve), meta: { transition: 'instant', preload: true, keepAlive: true } },
// 生产领料
{path: "/production",name: "salesReturn", component: resolve => require(["@/views/modules/production-pick/production.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
{path: "/productionPicking",name: "productionPicking", component: resolve => require(["@/views/modules/production-pick/productionPicking.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
{path: "/productionPickingDetail/:buNo/:outboundNo",name: "productionPickingDetail", component: resolve => require(["@/views/modules/production-pick/productionPickingDetail.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
{ path: "/production", name: "salesReturn", component: resolve => require(["@/views/modules/production-pick/production.vue"], resolve), meta: { transition: 'instant', preload: true, keepAlive: true } },
{ path: "/productionPicking", name: "productionPicking", component: resolve => require(["@/views/modules/production-pick/productionPicking.vue"], resolve), meta: { transition: 'instant', preload: true, keepAlive: true } },
{ path: "/productionPickingDetail/:buNo/:outboundNo", name: "productionPickingDetail", component: resolve => require(["@/views/modules/production-pick/productionPickingDetail.vue"], resolve), meta: { transition: 'instant', preload: true, keepAlive: true } },
// 生产入库
{path: "/productionInbound",name: "productionInbound",
component: resolve => require(["@/views/modules/production/production-inbound.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
{path: "/productionQualifiedStorage",name: "productionQualifiedStorage",
component: resolve => require(["@/views/modules/production/productionQualifiedStorage.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
{path: "/productionInboundStorage/:buNo/:inboundNo",name: "productionInboundStorage",
component: resolve => require(["@/views/modules/production/productionInboundStorage.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
{
path: "/productionInbound", name: "productionInbound",
component: resolve => require(["@/views/modules/production/production-inbound.vue"], resolve), meta: { transition: 'instant', preload: true, keepAlive: true }
},
{
path: "/productionQualifiedStorage", name: "productionQualifiedStorage",
component: resolve => require(["@/views/modules/production/productionQualifiedStorage.vue"], resolve), meta: { transition: 'instant', preload: true, keepAlive: true }
},
{
path: "/productionInboundStorage/:buNo/:inboundNo", name: "productionInboundStorage",
component: resolve => require(["@/views/modules/production/productionInboundStorage.vue"], resolve), meta: { transition: 'instant', preload: true, keepAlive: true }
},
// 销售出库
{path: "/salesOutbound",name: "salesOutbound",
component: resolve => require(["@/views/modules/sales/sales-outbound.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
{path: "/salesOutboundList",name: "salesOutboundList",
component: resolve => require(["@/views/modules/sales/salesOutboundList.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
{path: "/salesOutboundDetail/:buNo/:outboundNo",name: "salesOutboundDetail",
component: resolve => require(["@/views/modules/sales/salesOutboundDetail.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
{
path: "/salesOutbound", name: "salesOutbound",
component: resolve => require(["@/views/modules/sales/sales-outbound.vue"], resolve), meta: { transition: 'instant', preload: true, keepAlive: true }
},
{
path: "/salesOutboundList", name: "salesOutboundList",
component: resolve => require(["@/views/modules/sales/salesOutboundList.vue"], resolve), meta: { transition: 'instant', preload: true, keepAlive: true }
},
{
path: "/salesOutboundDetail/:buNo/:outboundNo", name: "salesOutboundDetail",
component: resolve => require(["@/views/modules/sales/salesOutboundDetail.vue"], resolve), meta: { transition: 'instant', preload: true, keepAlive: true }
},
// 采购退货
{path: "/purchaseReturn",name: "purchaseReturn",
component: resolve => require(["@/views/modules/purchase-return/purchase-return.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
{path: "/purchaseReturnList",name: "purchaseReturnList",
component: resolve => require(["@/views/modules/purchase-return/purchaseReturnList.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
{path: "/purchaseReturnDetail/:buNo/:returnNo",name: "purchaseReturnDetail",
component: resolve => require(["@/views/modules/purchase-return/purchaseReturnDetail.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
{
path: "/purchaseReturn", name: "purchaseReturn",
component: resolve => require(["@/views/modules/purchase-return/purchase-return.vue"], resolve), meta: { transition: 'instant', preload: true, keepAlive: true }
},
{
path: "/purchaseReturnList", name: "purchaseReturnList",
component: resolve => require(["@/views/modules/purchase-return/purchaseReturnList.vue"], resolve), meta: { transition: 'instant', preload: true, keepAlive: true }
},
{
path: "/purchaseReturnDetail/:buNo/:returnNo", name: "purchaseReturnDetail",
component: resolve => require(["@/views/modules/purchase-return/purchaseReturnDetail.vue"], resolve), meta: { transition: 'instant', preload: true, keepAlive: true }
},
// 其他出入库
{
path: "/otherInout", name: "otherInout",
component: resolve => require(["@/views/modules/other-inout/other-inout.vue"], resolve), meta: { transition: 'instant', preload: true, keepAlive: true }
},
// 其他出库
{path: "/otherInout",name: "otherInout",
component: resolve => require(["@/views/modules/other-inout/other-inout.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
{path: "/otherOutboundList",name: "otherOutboundList",
component: resolve => require(["@/views/modules/other-inout/otherOutboundList.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
{path: "/otherOutboundDetail/:buNo/:outboundNo",name: "otherOutboundDetail",
component: resolve => require(["@/views/modules/other-inout/otherOutboundDetail.vue"], resolve), meta: { transition: 'instant' ,preload: true,keepAlive: true}},
{
path: "/otherOutboundList", name: "otherOutboundList",
component: resolve => require(["@/views/modules/other-inout/otherOutboundList.vue"], resolve), meta: { transition: 'instant', preload: true, keepAlive: true }
},
{
path: "/otherOutboundDetail/:buNo/:outboundNo", name: "otherOutboundDetail",
component: resolve => require(["@/views/modules/other-inout/otherOutboundDetail.vue"], resolve), meta: { transition: 'instant', preload: true, keepAlive: true }
},
// 其他入库
{
path: "/otherInboundList", name: "otherInboundList",
component: resolve => require(["@/views/modules/other-inout/otherInboundList.vue"], resolve), meta: { transition: 'instant', preload: true, keepAlive: true }
},
{
path: "/otherInboundDetail/:inboundNo/:buNo", name: "otherInboundDetail",
component: resolve => require(["@/views/modules/other-inout/otherInboundDetail.vue"], resolve), meta: { transition: 'instant', preload: true, keepAlive: true }
},
// 属性变动
{
path: "/propertyChange", name: "propertyChange",
component: resolve => require(["@/views/modules/property-change/propertyChange.vue"], resolve), meta: { transition: 'instant', preload: true, keepAlive: true }
},
// 拆合组托
{
path: "/labelSplitMerge", name: "labelSplitMerge",
component: resolve => require(["@/views/modules/label-split-merge/labelSplitMerge.vue"], resolve), meta: { transition: 'instant', preload: true, keepAlive: true }
},
]
@ -88,8 +140,8 @@ const mainRoutes = {
children: [
{ path: '/home', component: _import('common/home'), name: 'home', meta: { title: '首页' } },
],
beforeEnter (to, from, next) {
let token =Vue.cookie.get('token')
beforeEnter(to, from, next) {
let token = Vue.cookie.get('token')
if (!token || !/\S/.test(token)) {
clearLoginInfo()
next({ name: 'login' })
@ -117,8 +169,8 @@ router.beforeEach((to, from, next) => {
http({
url: http.adornUrl('/sys/menu/nav'),
method: 'get',
params: {'l': i18n.locale,menuType: "pc"}
}).then(({data}) => {
params: { 'l': i18n.locale, menuType: "pc" }
}).then(({ data }) => {
if (data && data.code === 0) {
//fnAddDynamicMenuRoutes(data.menuList)
//router.options.isAddDynamicMenuRoutes = true
@ -139,7 +191,7 @@ router.beforeEach((to, from, next) => {
* 判断当前路由类型, global: 全局路由, main: 主入口路由
* @param {*} route 当前路由
*/
function fnCurrentRouteType (route, globalRoutes = []) {
function fnCurrentRouteType(route, globalRoutes = []) {
var temp = []
for (var i = 0; i < globalRoutes.length; i++) {
if (route.path === globalRoutes[i].path) {

4
src/views/main.vue

@ -107,7 +107,7 @@
<span class="section-title">库内管理</span>
</div>
<div class="button-grid">
<div class="menu-item" @click="navigateWithWarehouseCheck('attributechange')">
<div class="menu-item" @click="navigateWithWarehouseCheck('propertyChange')">
<div class="menu-icon attribute">
<van-icon name="setting-o" size="24" />
</div>
@ -137,7 +137,7 @@
</div>
<div class="menu-text">跨区调拨</div>
</div>
<div class="menu-item" @click="navigateWithWarehouseCheck('handlingunit')">
<div class="menu-item" @click="navigateWithWarehouseCheck('labelSplitMerge')">
<div class="menu-icon hu">
<van-icon name="cluster-o" size="24" />
</div>

629
src/views/modules/label-split-merge/labelSplitMerge.vue

@ -0,0 +1,629 @@
<template>
<div class="pda-container">
<!-- 头部栏 -->
<div class="header-bar">
<div class="header-left" @click="$router.back()">
<i class="el-icon-arrow-left"></i>
<span>拆合组托</span>
</div>
<div class="header-right" @click="$router.push({ path: '/' })">
首页
</div>
</div>
<!-- 搜索框 -->
<div class="search-container">
<el-input
v-model="scanCode"
placeholder="请扫描标签条码"
prefix-icon="el-icon-search"
@keyup.enter.native="handleScan"
ref="scanInput"
clearable
/>
</div>
<!-- 标签信息卡片 -->
<div class="label-info-card">
<div class="info-row">
<span class="info-label">标签条码</span>
<span class="info-value">{{ currentLabel.labelCode || ''}}</span>
</div>
<div class="info-row">
<span class="info-label">标签类型</span>
<span class="info-value">{{ currentLabel.labelType || '' }}</span>
</div>
<div class="info-row">
<span class="info-label">标签张数</span>
<span class="info-value">{{ currentLabel.labelQty || ''}}</span>
</div>
<div class="info-row">
<span class="info-label">标签数量</span>
<span class="info-value">{{ currentLabel.qtyOnHand || ''}}</span>
</div>
<div class="info-row">
<span class="info-label">所在仓库</span>
<span class="info-value">{{ currentLabel.warehouseName || ''}}</span>
</div>
<div class="info-row">
<span class="info-label">所在库位</span>
<span class="info-value">{{ currentLabel.locationId || ''}}</span>
</div>
<div class="info-row">
<span class="info-label">标签状态</span>
<span class="info-value" :class="currentLabel.status === '冻结' ? 'status-frozen' : 'status-normal'">{{ currentLabel.status || ''}}</span>
</div>
</div>
<!-- 操作按钮 -->
<div class="action-buttons" v-if="currentLabel.labelCode">
<button class="action-btn split-btn" @click="showSplitDialog">
拆分
</button>
<button class="action-btn merge-btn" @click="showMergeDialog">
合并
</button>
</div>
<!-- 拆分对话框 -->
<div v-if="splitDialogVisible" class="dialog-overlay">
<div class="dialog-modal">
<div class="dialog-header">
<span class="dialog-title">标签的拆分</span>
</div>
<div class="dialog-body">
<div class="split-input-section">
<el-input
v-model="splitQuantity"
placeholder="请输入拆分数量"
type="number"
class="split-input"
/>
</div>
</div>
<div class="dialog-footer">
<button class="btn-split" @click="confirmSplit" :disabled="!splitQuantity || splitQuantity <= 0">
拆分
</button>
<button class="btn-cancel" @click="closeSplitDialog">
取消
</button>
</div>
</div>
</div>
<!-- 合并对话框 -->
<div v-if="mergeDialogVisible" class="dialog-overlay">
<div class="dialog-modal">
<div class="dialog-header">
<span class="dialog-title">标签的合并</span>
</div>
<div class="dialog-body">
<div class="merge-input-section">
<el-input
v-model="mergeTargetCode"
placeholder="请扫描合并标签"
prefix-icon="el-icon-search"
class="merge-input"
ref="mergeInput"
/>
</div>
</div>
<div class="dialog-footer">
<button class="btn-merge" @click="confirmMerge" :disabled="!mergeTargetCode.trim()">
合并
</button>
<button class="btn-cancel" @click="closeMergeDialog">
取消
</button>
</div>
</div>
</div>
</div>
</template>
<script>
import { getStockInfoByLabelCode, splitLabel, mergeLabel } from "@/api/label-split-merge/label-split-merge.js";
import { getCurrentWarehouse } from '@/utils'
export default {
data() {
return {
scanCode: '',
currentLabel: {},
splitDialogVisible: false,
mergeDialogVisible: false,
splitQuantity: '',
mergeTargetCode: '',
mergeTargetLabel: {}
};
},
methods: {
//
handleScan() {
if (!this.scanCode.trim()) {
return;
}
this.getStockInfo(this.scanCode.trim());
this.scanCode = '';
},
//
getStockInfo(labelCode) {
const params = {
labelCode: labelCode,
site: localStorage.getItem('site'),
warehouseId: getCurrentWarehouse()
};
getStockInfoByLabelCode(params).then(({ data }) => {
if (data && data.code === 0) {
this.currentLabel = data.data;
this.$message.success('获取标签信息成功');
} else {
this.$message.error(data.msg || '未找到该标签的库存信息');
this.currentLabel = {};
}
}).catch(error => {
console.error('获取库存信息失败:', error);
this.$message.error('获取库存信息失败');
this.currentLabel = {};
});
},
//
showSplitDialog() {
if (this.currentLabel.qtyOnHand <= 1) {
this.$message.warning('标签数量必须大于1才能拆分');
return;
}
this.splitDialogVisible = true;
this.splitQuantity = '';
},
//
closeSplitDialog() {
this.splitDialogVisible = false;
this.splitQuantity = '';
},
//
confirmSplit() {
const splitQty = parseFloat(this.splitQuantity);
const currentQty = parseFloat(this.currentLabel.qtyOnHand);
if (!splitQty || splitQty <= 0) {
this.$message.warning('请输入有效的拆分数量');
return;
}
if (splitQty >= currentQty) {
this.$message.warning('拆分数量必须小于当前数量');
return;
}
const params = {
site: localStorage.getItem('site'),
buNo: this.currentLabel.buNo,
warehouseId: getCurrentWarehouse(),
originalLabelCode: this.currentLabel.labelCode,
wdr: this.currentLabel.wdr,
partNo: this.currentLabel.partNo,
batchNo: this.currentLabel.batchNo,
locationId: this.currentLabel.locationId,
originalQuantity: currentQty,
splitQuantity: splitQty,
labelTypeTb: this.currentLabel.labelTypeTb,
labelType: this.currentLabel.labelType,
freezeFlag: this.currentLabel.freezeFlag,
manufactureDate: this.currentLabel.productionDate,
expiredDate: this.currentLabel.expiryDate,
orderref1: this.currentLabel.orderref1,
orderref2: this.currentLabel.orderref2,
orderref3: this.currentLabel.orderref3
};
splitLabel(params).then(({ data }) => {
if (data && data.code === 0) {
this.$message.success(`拆分成功!新标签: ${data.data.newLabelCode}`);
this.closeSplitDialog();
//
this.getStockInfo(this.currentLabel.labelCode);
} else {
this.$message.error(data.msg || '拆分失败');
}
}).catch(error => {
console.error('拆分失败:', error);
this.$message.error('拆分失败');
});
},
//
showMergeDialog() {
this.mergeDialogVisible = true;
this.mergeTargetCode = '';
this.mergeTargetLabel = {};
this.$nextTick(() => {
if (this.$refs.mergeInput) {
this.$refs.mergeInput.focus();
}
});
},
//
closeMergeDialog() {
this.mergeDialogVisible = false;
this.mergeTargetCode = '';
this.mergeTargetLabel = {};
},
//
confirmMerge() {
if (!this.mergeTargetCode.trim()) {
this.$message.warning('请扫描目标标签');
return;
}
if (this.mergeTargetCode.trim() === this.currentLabel.labelCode) {
this.$message.warning('不能合并到自己');
return;
}
//
const params = {
labelCode: this.mergeTargetCode.trim(),
site: localStorage.getItem('site'),
warehouseId: getCurrentWarehouse()
};
getStockInfoByLabelCode(params).then(({ data }) => {
if (data && data.code === 0) {
const targetLabel = data.data;
//
if (targetLabel.partNo !== this.currentLabel.partNo) {
this.$message.error('不同物料不能合并');
return;
}
if (targetLabel.batchNo !== this.currentLabel.batchNo) {
this.$message.error('不同批次不能合并');
return;
}
//
const mergeParams = {
site: localStorage.getItem('site'),
buNo: this.currentLabel.buNo,
warehouseId: getCurrentWarehouse(),
targetLabelCode: targetLabel.labelCode,
sourceLabelCode: this.currentLabel.labelCode,
partNo: this.currentLabel.partNo,
batchNo: this.currentLabel.batchNo,
locationId: this.currentLabel.locationId,
targetQuantity: parseFloat(targetLabel.qtyOnHand),
sourceQuantity: parseFloat(this.currentLabel.qtyOnHand)
};
mergeLabel(mergeParams).then(({ data }) => {
if (data && data.code === 0) {
this.$message.success('合并成功!');
this.closeMergeDialog();
//
this.currentLabel = {};
//
this.$nextTick(() => {
if (this.$refs.scanInput) {
this.$refs.scanInput.focus();
}
});
} else {
this.$message.error(data.msg || '合并失败');
}
}).catch(error => {
console.error('合并失败:', error);
this.$message.error('合并失败');
});
} else {
this.$message.error(data.msg || '未找到目标标签的库存信息');
}
}).catch(error => {
console.error('获取目标标签信息失败:', error);
this.$message.error('获取目标标签信息失败');
});
}
},
mounted() {
//
this.$nextTick(() => {
if (this.$refs.scanInput) {
this.$refs.scanInput.focus();
}
});
}
};
</script>
<style scoped>
.pda-container {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
background: #f5f5f5;
}
/* 头部栏 */
.header-bar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 16px;
background: #17B3A3;
color: white;
height: 40px;
min-height: 40px;
}
.header-left {
display: flex;
align-items: center;
cursor: pointer;
font-size: 16px;
font-weight: 500;
}
.header-left i {
margin-right: 8px;
font-size: 18px;
}
.header-right {
cursor: pointer;
font-size: 16px;
font-weight: 500;
}
/* 搜索容器 */
.search-container {
padding: 12px 16px;
background: white;
}
.search-container .el-input {
width: 100%;
}
/* 标签信息卡片 */
.label-info-card {
background: white;
margin: 8px 16px;
padding: 16px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
flex: 1;
overflow-y: auto;
}
.info-row {
display: flex;
align-items: center;
margin-bottom: 16px;
min-height: 40px;
}
.info-label {
width: 80px;
font-size: 14px;
color: #333;
font-weight: 500;
flex-shrink: 0;
}
.info-value {
flex: 1;
font-size: 14px;
color: #666;
margin-left: 12px;
}
.status-frozen {
color: #ff4949;
font-weight: 500;
}
.status-normal {
color: #17B3A3;
font-weight: 500;
}
/* 操作按钮 */
.action-buttons {
display: flex;
padding: 16px;
gap: 12px;
background: white;
margin-top: auto;
}
.action-btn {
flex: 1;
padding: 12px;
border-radius: 20px;
font-size: 14px;
cursor: pointer;
transition: all 0.2s ease;
border: none;
}
.split-btn {
background: #17B3A3;
color: white;
}
.split-btn:hover {
background: #0d8f7f;
}
.merge-btn {
background: white;
color: #17B3A3;
border: 1px solid #17B3A3;
}
.merge-btn:hover {
background: #17B3A3;
color: white;
}
.action-btn:active {
transform: scale(0.98);
}
/* 对话框样式 */
.dialog-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
.dialog-modal {
background: white;
border-radius: 12px;
width: 100%;
max-width: 400px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
overflow: hidden;
}
.dialog-header {
background: #17B3A3;
color: white;
padding: 16px 20px;
text-align: center;
}
.dialog-title {
font-size: 16px;
font-weight: 500;
}
.dialog-body {
padding: 20px;
}
.split-input-section,
.merge-input-section {
margin-bottom: 20px;
}
.split-input,
.merge-input {
width: 100%;
}
.split-input ::v-deep .el-input__inner,
.merge-input ::v-deep .el-input__inner {
height: 48px;
border: 1px solid #17B3A3;
border-radius: 8px;
font-size: 16px;
text-align: center;
}
.dialog-footer {
padding: 16px 20px;
display: flex;
justify-content: center;
gap: 12px;
border-top: 1px solid #f0f0f0;
}
.btn-split,
.btn-merge,
.btn-cancel {
padding: 10px 20px;
border-radius: 6px;
font-size: 14px;
cursor: pointer;
transition: all 0.2s;
border: none;
outline: none;
}
.btn-split,
.btn-merge {
background: #17B3A3;
color: white;
}
.btn-split:hover:not(:disabled),
.btn-merge:hover:not(:disabled) {
background: #0d8f7f;
}
.btn-split:disabled,
.btn-merge:disabled {
background: #c0c4cc;
cursor: not-allowed;
}
.btn-cancel {
background: #f5f5f5;
color: #666;
}
.btn-cancel:hover {
background: #e6e6e6;
}
/* 响应式设计 */
@media (max-width: 360px) {
.header-bar {
padding: 8px 12px;
}
.search-container {
padding: 8px 12px;
}
.label-info-card {
margin: 6px 12px;
padding: 12px;
}
.info-label {
width: 70px;
font-size: 13px;
}
.info-value {
font-size: 13px;
}
.action-buttons {
padding: 12px;
}
}
</style>

1327
src/views/modules/other-inout/otherInboundDetail.vue
File diff suppressed because it is too large
View File

400
src/views/modules/other-inout/otherInboundList.vue

@ -0,0 +1,400 @@
<template>
<div class="pda-container">
<!-- 头部栏 -->
<div class="header-bar">
<div class="header-left" @click="$router.back()">
<i class="el-icon-arrow-left"></i>
<span>其它入库</span>
</div>
<div class="header-right" @click="$router.push({ path: '/' })">
首页
</div>
</div>
<!-- 搜索框 -->
<div class="search-container">
<el-input clearable
v-model="searchCode"
placeholder="请扫描入库单或关联单号"
prefix-icon="el-icon-search"
@keyup.enter.native="handleSearch"
ref="searchInput"
/>
</div>
<!-- 入库单列表 -->
<div class="content-area">
<div
v-for="(item, index) in inboundList"
:key="index"
class="inbound-card"
@click="goToInboundPage(item)"
>
<div class="card-title">
<span class="title-label">入库单号</span>
<span class="title-value">{{ item.inboundNo }}</span>
</div>
<div class="card-details">
<div class="detail-item">
<div class="detail-label">关联订单</div>
<div class="detail-value">{{ item.relatedNo }}</div>
</div>
<div class="detail-item">
<div class="detail-label">标签张数</div>
<div class="detail-value">
<span class="qualified">{{ item.totalLabels }}</span>
</div>
</div>
<div class="detail-item">
<div class="detail-label">物料总数</div>
<div class="detail-value">
<span class="qualified">{{ item.totalQty }}</span>
</div>
</div>
</div>
</div>
<!-- 空状态 -->
<div v-if="inboundList.length === 0 && !loading" class="empty-state">
<i class="el-icon-box"></i>
<p>暂无待入库单据</p>
</div>
<!-- 加载状态 -->
<div v-if="loading" class="loading-state">
<i class="el-icon-loading"></i>
<p>加载中...</p>
</div>
</div>
</div>
</template>
<script>
import { getOtherInboundList } from "@/api/other-inbound/other-inbound.js";
import { getCurrentWarehouse } from '@/utils'
import moment from 'moment';
export default {
data() {
return {
searchCode: '',
inboundList: [],
loading: false
};
},
methods: {
formatDate(date) {
return date ? moment(date).format('YYYY-MM-DD') : '';
},
//
handleSearch() {
if (this.searchCode.trim()) {
this.searchInboundList(this.searchCode.trim());
} else {
this.loadInboundList();
}
},
//
loadInboundList() {
const currentWarehouse = getCurrentWarehouse();
if (!currentWarehouse) {
this.$message.error('请先选择仓库');
return;
}
this.loading = true;
const params = {
warehouseId: currentWarehouse,
site: localStorage.getItem('site'),
status: '待入库',
};
getOtherInboundList(params).then(({ data }) => {
this.loading = false;
if (data && data.code === 0) {
this.inboundList = data.data || [];
} else {
this.$message.error(data.msg || '获取数据失败');
}
}).catch(error => {
this.loading = false;
console.error('获取其他入库单列表失败:', error);
this.$message.error('获取数据失败');
});
},
//
searchInboundList(searchCode) {
const currentWarehouse = getCurrentWarehouse();
if (!currentWarehouse) {
this.$message.error('请先选择仓库');
return;
}
this.loading = true;
const params = {
warehouseId: currentWarehouse,
searchCode: searchCode,
site: localStorage.getItem('site'),
status: '待入库'
};
getOtherInboundList(params).then(({ data }) => {
this.loading = false;
if (data && data.code === 0) {
if (data.data.length === 0) {
this.$message.warning('未找到匹配的入库单');
}
this.inboundList = data.data || [];
} else {
this.$message.error(data.msg || '查询失败');
}
}).catch(error => {
this.loading = false;
console.error('搜索失败:', error);
this.$message.error('查询失败');
});
},
//
goToInboundPage(item) {
this.$router.push({
name: 'otherInboundDetail',
params: {
inboundNo: item.inboundNo,
buNo: item.buNo
}
});
}
},
mounted() {
//
this.$nextTick(() => {
if (this.$refs.searchInput) {
this.$refs.searchInput.focus();
}
});
//
this.loadInboundList();
}
};
</script>
<style scoped>
.pda-container {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
background: #f5f5f5;
}
/* 头部栏 */
.header-bar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 16px;
background: #17B3A3;
color: white;
height: 40px;
min-height: 40px;
}
.header-left {
display: flex;
align-items: center;
cursor: pointer;
font-size: 16px;
font-weight: 500;
}
.header-left i {
margin-right: 8px;
font-size: 18px;
}
.header-right {
cursor: pointer;
font-size: 16px;
font-weight: 500;
}
/* 搜索容器 */
.search-container {
padding: 12px 16px;
background: white;
}
/* 内容区域 */
.content-area {
flex: 1;
overflow-y: auto;
padding: 12px 16px;
}
/* 入库卡片 */
.inbound-card {
background: white;
border-radius: 8px;
margin-bottom: 12px;
padding: 16px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
cursor: pointer;
transition: all 0.2s ease;
}
.inbound-card:hover {
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
transform: translateY(-1px);
}
.inbound-card:active {
transform: translateY(0);
}
/* 卡片标题 */
.card-title {
margin-bottom: 12px;
}
.title-label {
font-size: 12px;
color: #666;
display: block;
margin-bottom: 4px;
}
.title-value {
font-size: 16px;
font-weight: bold;
color: #333;
margin-left: 20px;
}
/* 卡片详情 */
.card-details {
display: flex;
justify-content: space-between;
align-items: flex-start;
gap: 4px;
}
.detail-item {
flex: 1;
text-align: center;
min-width: 60px;
max-width: 60px;
}
.detail-label {
font-size: 11px;
color: #666;
margin-bottom: 4px;
line-height: 1.2;
margin-left: -12px;
}
.detail-value {
font-size: 13px;
color: #333;
line-height: 1.2;
margin-left: -12px;
}
.detail-value .qualified {
color: #17B3A3;
font-weight: 500;
}
.detail-value .total {
color: #333;
font-weight: 500;
}
.detail-value .total::before {
content: '/';
color: #333;
}
/* 空状态 */
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 60px 20px;
color: #999;
}
.empty-state i {
font-size: 48px;
margin-bottom: 16px;
}
.empty-state p {
font-size: 14px;
margin: 0;
}
/* 加载状态 */
.loading-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 60px 20px;
color: #17B3A3;
}
.loading-state i {
font-size: 24px;
margin-bottom: 12px;
animation: spin 1s linear infinite;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.loading-state p {
font-size: 14px;
margin: 0;
}
/* 响应式设计 */
@media (max-width: 360px) {
.header-bar {
padding: 8px 12px;
}
.search-container {
padding: 8px 12px;
}
.content-area {
padding: 8px 12px;
}
.inbound-card {
padding: 12px;
}
.card-details {
flex-wrap: wrap;
gap: 6px;
}
.detail-item {
flex: 0 0 48%;
margin-bottom: 6px;
min-width: 50px;
}
}
</style>

2
src/views/modules/other-inout/otherOutboundDetail.vue

@ -18,7 +18,7 @@
placeholder="请扫描标签条码"
prefix-icon="el-icon-search"
@keyup.enter.native="handleScan"
ref="scanInput"
ref="scanInput" clearable
/>
<div class="mode-switch">
<el-switch

2
src/views/modules/production-pick/productionPicking.vue

@ -108,7 +108,7 @@ export default {
const params = {
warehouseId: currentWarehouse,
site: localStorage.getItem('site'),
status: '库',
status: '待出库',
};
getProductionOutboundList(params).then(({ data }) => {

4
src/views/modules/production-pick/productionPickingDetail.vue

@ -13,7 +13,7 @@
<!-- 搜索框 -->
<div class="search-container">
<el-input
<el-input clearable
v-model="scanCode"
placeholder="请扫描标签条码"
prefix-icon="el-icon-search"
@ -969,4 +969,4 @@ export default {
flex: 1.5;
}
}
</style>
</style>

4
src/views/modules/production/productionInboundStorage.vue

@ -13,7 +13,7 @@
<!-- 搜索框 -->
<div class="search-container">
<el-input
<el-input clearable
v-model="scanCode"
placeholder="请扫描标签条码"
prefix-icon="el-icon-search"
@ -1315,4 +1315,4 @@ export default {
padding: 6px 2px;
}
}
</style>
</style>

486
src/views/modules/property-change/propertyChange.vue

@ -0,0 +1,486 @@
<template>
<div class="pda-container">
<!-- 头部栏 -->
<div class="header-bar">
<div class="header-left" @click="$router.back()">
<i class="el-icon-arrow-left"></i>
<span>属性变动</span>
</div>
<div class="header-right" @click="$router.push({ path: '/' })">
首页
</div>
</div>
<!-- 搜索框 -->
<div class="search-container">
<el-input clearable
v-model="scanCode"
placeholder="请扫描标签条码"
prefix-icon="el-icon-search"
@keyup.enter.native="handleScan"
ref="scanInput"
/>
</div>
<!-- 标签信息卡片 -->
<div class="label-info-card" >
<div class="info-row">
<span class="info-label">标签条码</span>
<span class="info-value">{{ stockInfo.labelCode || '' }}</span>
</div>
<div class="info-row">
<span class="info-label">标签数量</span>
<span class="info-value">{{ stockInfo.labelQuantity || '' }}</span>
</div>
<div class="info-row">
<span class="info-label">所在仓库</span>
<span class="info-value">{{ stockInfo.warehouseName || '' }}</span>
</div>
<div class="info-row">
<span class="info-label">所在库位</span>
<div class="input-wrapper">
<el-input
v-model="newLocationId"
placeholder="请扫描/输入库位"
class="location-input"
@keyup.enter.native="focusNextInput"
/>
</div>
</div>
<div class="info-row">
<span class="info-label">标签状态</span>
<span class="info-value" :class="stockInfo.status === '冻结' ? 'status-frozen' : 'status-normal'">{{ stockInfo.status || '' }}</span>
</div>
<div class="info-row">
<span class="info-label">生产日期</span>
<div class="input-wrapper">
<el-date-picker
v-model="newProductionDate"
type="date"
placeholder="选择生产日期"
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"
class="date-input"
/>
</div>
</div>
<div class="info-row">
<span class="info-label">有效期截止</span>
<div class="input-wrapper">
<el-date-picker
v-model="newExpiryDate"
type="date"
placeholder="选择有效期"
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"
class="date-input"
/>
</div>
</div>
<div class="info-row">
<span class="info-label">关联单号1</span>
<span class="info-value">{{ stockInfo.orderref1 || '-' }}</span>
</div>
<div class="info-row">
<span class="info-label">关联单号2</span>
<span class="info-value">{{ stockInfo.orderref2 || '-' }}</span>
</div>
<div class="info-row">
<span class="info-label">批次号</span>
<span class="info-value">{{ stockInfo.batchNo || ''}}</span>
</div>
</div>
<!-- 底部操作按钮 -->
<div class="bottom-actions" v-if="stockInfo.labelCode">
<button class="action-btn primary" @click="confirmChange">
确定
</button>
<button class="action-btn secondary" @click="cancelChange">
取消
</button>
</div>
</div>
</template>
<script>
import { getStockInfoByLabelCode, savePropertyChange } from "@/api/property-change/property-change.js";
import { getCurrentWarehouse } from '@/utils'
import moment from 'moment';
export default {
data() {
return {
scanCode: '',
stockInfo: {},
newLocationId: '',
newProductionDate: '',
newExpiryDate: ''
};
},
methods: {
//
handleScan() {
if (!this.scanCode.trim()) {
return;
}
this.getStockInfo(this.scanCode.trim());
this.scanCode = '';
},
//
getStockInfo(labelCode) {
const params = {
labelCode: labelCode,
site: localStorage.getItem('site'),
warehouseId: getCurrentWarehouse()
};
getStockInfoByLabelCode(params).then(({ data }) => {
if (data && data.code === 0) {
this.stockInfo = data.data;
//
this.newLocationId = this.stockInfo.locationId || '';
this.newProductionDate = this.stockInfo.productionDate ? moment(this.stockInfo.productionDate).format('YYYY-MM-DD') : '';
this.newExpiryDate = this.stockInfo.expiryDate ? moment(this.stockInfo.expiryDate).format('YYYY-MM-DD') : '';
this.$message.success('获取标签信息成功');
} else {
this.$message.error(data.msg || '未找到该标签的库存信息');
this.stockInfo = {};
}
}).catch(error => {
console.error('获取库存信息失败:', error);
this.$message.error('获取库存信息失败');
this.stockInfo = {};
});
},
//
focusNextInput() {
//
},
//
confirmChange() {
if (!this.stockInfo.labelCode) {
this.$message.warning('请先扫描标签条码');
return;
}
//
const oldLocationId = this.stockInfo.locationId || '';
const oldProductionDate = this.stockInfo.productionDate ? moment(this.stockInfo.productionDate).format('YYYY-MM-DD') : '';
const oldExpiryDate = this.stockInfo.expiryDate ? moment(this.stockInfo.expiryDate).format('YYYY-MM-DD') : '';
const hasLocationChange = this.newLocationId !== oldLocationId;
const hasProductionDateChange = this.newProductionDate !== oldProductionDate;
const hasExpiryDateChange = this.newExpiryDate !== oldExpiryDate;
if (!hasLocationChange && !hasProductionDateChange && !hasExpiryDateChange) {
this.$message.warning('没有检测到属性变动,请修改后再提交');
return;
}
//
const params = {
site: localStorage.getItem('site'),
buNo: this.stockInfo.buNo,
warehouseId: getCurrentWarehouse(),
labelCode: this.stockInfo.labelCode,
partNo: this.stockInfo.partNo,
batchNo: this.stockInfo.batchNo,
quantity: this.stockInfo.qtyOnHand,
oldLocationId: oldLocationId,
newLocationId: this.newLocationId,
oldProductionDate: oldProductionDate,
newProductionDate: this.newProductionDate,
oldExpiryDate: oldExpiryDate,
newExpiryDate: this.newExpiryDate
};
//
let changeMsg = '确认进行以下属性变动?\n';
if (hasLocationChange) {
changeMsg += `库位: ${oldLocationId}${this.newLocationId}\n`;
}
if (hasProductionDateChange) {
changeMsg += `生产日期: ${oldProductionDate}${this.newProductionDate}\n`;
}
if (hasExpiryDateChange) {
changeMsg += `有效期: ${oldExpiryDate}${this.newExpiryDate}\n`;
}
this.$confirm(changeMsg, '确认变动', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.saveChange(params);
}).catch(() => {
//
});
},
//
saveChange(params) {
savePropertyChange(params).then(({ data }) => {
if (data && data.code === 0) {
this.$message.success('操作成功');
this.resetForm();
} else {
this.$message.error(data.msg || '保存失败');
}
}).catch(error => {
console.error('保存属性变动失败:', error);
this.$message.error('保存失败');
});
},
//
cancelChange() {
if (this.stockInfo.labelCode) {
this.$confirm('确定要取消当前操作吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '继续操作',
type: 'warning'
}).then(() => {
this.resetForm();
}).catch(() => {
//
});
} else {
this.$router.back();
}
},
//
resetForm() {
this.stockInfo = {};
this.newLocationId = '';
this.newProductionDate = '';
this.newExpiryDate = '';
//
this.$nextTick(() => {
if (this.$refs.scanInput) {
this.$refs.scanInput.focus();
}
});
}
},
mounted() {
//
this.$nextTick(() => {
if (this.$refs.scanInput) {
this.$refs.scanInput.focus();
}
});
}
};
</script>
<style scoped>
.pda-container {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
background: #f5f5f5;
}
/* 头部栏 */
.header-bar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 16px;
background: #17B3A3;
color: white;
height: 40px;
min-height: 40px;
}
.header-left {
display: flex;
align-items: center;
cursor: pointer;
font-size: 16px;
font-weight: 500;
}
.header-left i {
margin-right: 8px;
font-size: 18px;
}
.header-right {
cursor: pointer;
font-size: 16px;
font-weight: 500;
}
/* 搜索容器 */
.search-container {
padding: 12px 16px;
background: white;
}
.search-container .el-input {
width: 100%;
}
/* 标签信息卡片 */
.label-info-card {
background: white;
margin: 8px 16px;
padding: 16px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
flex: 1;
overflow-y: auto;
}
.info-row {
display: flex;
align-items: center;
margin-bottom: 2px;
min-height: 40px;
}
.info-label {
width: 80px;
font-size: 14px;
color: #333;
font-weight: 500;
flex-shrink: 0;
}
.info-value {
flex: 1;
font-size: 14px;
color: #666;
margin-left: 12px;
}
.status-frozen {
color: #ff4949;
font-weight: 500;
}
.status-normal {
color: #17B3A3;
font-weight: 500;
}
.input-wrapper {
flex: 1;
margin-left: 12px;
}
.location-input {
width: 100%;
}
.location-input ::v-deep .el-input__inner {
border: 1px solid #17B3A3;
border-radius: 4px;
font-size: 14px;
padding: 8px 12px;
}
.date-input {
width: 100%;
}
.date-input ::v-deep .el-input__inner {
border: 1px solid #17B3A3;
border-radius: 4px;
font-size: 14px;
padding: 8px 12px;
}
/* 底部操作按钮 */
.bottom-actions {
display: flex;
padding: 16px;
gap: 12px;
background: white;
margin-top: auto;
}
.action-btn {
flex: 1;
padding: 12px;
border-radius: 20px;
font-size: 14px;
cursor: pointer;
transition: all 0.2s ease;
border: none;
}
.action-btn.primary {
background: #17B3A3;
color: white;
}
.action-btn.primary:hover {
background: #0d8f7f;
}
.action-btn.secondary {
background: white;
color: #17B3A3;
border: 1px solid #17B3A3;
}
.action-btn.secondary:hover {
background: #17B3A3;
color: white;
}
.action-btn:active {
transform: scale(0.98);
}
/* 响应式设计 */
@media (max-width: 360px) {
.header-bar {
padding: 8px 12px;
}
.search-container {
padding: 8px 12px;
}
.label-info-card {
margin: 6px 12px;
padding: 12px;
}
.info-label {
width: 70px;
font-size: 13px;
}
.info-value {
font-size: 13px;
}
.bottom-actions {
padding: 12px;
}
}
</style>

4
src/views/modules/purchase-inbound/inboundStorage.vue

@ -13,7 +13,7 @@
<!-- 搜索框 -->
<div class="search-container">
<el-input
<el-input clearable
v-model="scanCode"
placeholder="请扫描标签条码"
prefix-icon="el-icon-search"
@ -920,7 +920,7 @@ export default {
.modal-header {
background: #17B3A3;
color: white;
padding: 16px 20px;
padding: 12px 20px;
text-align: center;
}

2
src/views/modules/purchase-return/purchaseReturnDetail.vue

@ -13,7 +13,7 @@
<!-- 搜索框 -->
<div class="search-container">
<el-input
<el-input clearable
v-model="scanCode"
placeholder="请扫描标签条码"
prefix-icon="el-icon-search"

2
src/views/modules/sales-return/salesReturnStorage.vue

@ -13,7 +13,7 @@
<!-- 搜索框 -->
<div class="search-container">
<el-input
<el-input clearable
v-model="scanCode"
placeholder="请扫描标签条码"
prefix-icon="el-icon-search"

8
src/views/modules/sales/salesOutboundDetail.vue

@ -13,7 +13,7 @@
<!-- 搜索框 -->
<div class="search-container">
<el-input
<el-input clearable
v-model="scanCode"
placeholder="请扫描标签条码"
prefix-icon="el-icon-search"
@ -190,7 +190,7 @@ export default {
formatDate(date) {
return date ? moment(date).format('YYYY-MM-DD') : '';
},
//
handleScan() {
if (!this.scanCode.trim()) {
@ -273,7 +273,7 @@ export default {
batchNo: label.batchNo
}))
};
confirmSalesOutbound(params).then(({ data }) => {
if (data && data.code === 0) {
this.$message.success('出库成功');
@ -996,4 +996,4 @@ export default {
flex: 1.5;
}
}
</style>
</style>
Loading…
Cancel
Save