feat(采购模块): 实现订单选择组件并优化UI交互

refactor(采购管理): 替换输入框为选择组件提升用户体验
style(表格样式): 调整表格边框和间距优化视觉效果
This commit is contained in:
砂糖
2025-11-19 17:16:19 +08:00
parent 7d0492a545
commit 90f88bc36c
8 changed files with 251 additions and 139 deletions

View File

@@ -70,7 +70,7 @@ public class ErpPurchaseOrderServiceImpl implements IErpPurchaseOrderService {
private LambdaQueryWrapper<ErpPurchaseOrder> buildQueryWrapper(ErpPurchaseOrderBo bo) {
LambdaQueryWrapper<ErpPurchaseOrder> lqw = Wrappers.lambdaQuery();
lqw.eq(StringUtils.isNotBlank(bo.getOrderCode()), ErpPurchaseOrder::getOrderCode, bo.getOrderCode());
lqw.like(StringUtils.isNotBlank(bo.getOrderCode()), ErpPurchaseOrder::getOrderCode, bo.getOrderCode());
lqw.eq(bo.getSupplierId() != null, ErpPurchaseOrder::getSupplierId, bo.getSupplierId());
lqw.eq(bo.getOrderDate() != null, ErpPurchaseOrder::getOrderDate, bo.getOrderDate());
lqw.eq(bo.getExpectedArrival() != null, ErpPurchaseOrder::getExpectedArrival, bo.getExpectedArrival());

View File

@@ -318,7 +318,7 @@ body {
.el-table {
background: $--table-bg;
// border: 1px solid $--border-color-light;
border-radius: 8px;
border-radius: 0px;
box-shadow: 0 6px 16px rgba(20, 30, 50, 0.08);
color: $--color-text-regular;
overflow: hidden;
@@ -336,93 +336,16 @@ body {
color: $--color-text-primary;
font-weight: 600;
border-bottom: 1px solid $--border-color-lighter;
padding: 4px !important; // 紧凑 padding
padding: 0 !important; // 紧凑 padding
height: auto;
font-size: 13px;
}
}
// 表体(奇偶行交替 + hover高亮
.el-table__body-wrapper {
.el-table__row {
// 奇数行
&:nth-child(odd) .el-table__cell {
background: $--color-background-light;
color: $--color-text-regular;
}
// 偶数行
&:nth-child(even) .el-table__cell {
background: $--color-background-light;
color: $--color-text-regular;
}
// hover
&:hover .el-table__cell {
background: rgba($--color-primary, 0.12);
color: #4a4a4a;
}
&:hover .el-table__cell {
background: rgba($--color-primary, 0.12);
color: #4a4a4a;
}
// 当前行
&.current-row .el-table__cell {
background: rgba($--color-primary, 0.35);
color: $--color-text-primary;
font-weight: 600;
}
}
// 单元格(统一边框 + 紧凑 padding
.el-table__cell {
border-bottom: 1px solid $--border-color-lighter;
color: $--color-text-regular;
padding: 2px 4px !important; // 超紧凑
font-size: 13px;
}
}
// 表尾
.el-table__footer-wrapper {
border-top: 1px solid $--border-color-lighter;
td {
background: linear-gradient(0deg, $--color-background-light, $--color-background);
color: $--color-text-secondary;
padding: 4px !important;
}
}
// 列宽调整线
.el-table__column-resize-proxy {
background-color: $--color-primary;
}
// 展开图标
.el-table__expand-icon {
color: $--color-text-secondary;
&.is-expanded,
&:hover {
color: $--color-primary;
}
}
&__empty-block {
background: lighten($--color-background, 8%);
}
// 适配尺寸类(统一紧凑)
&.el-table--medium .el-table__cell,
&.el-table--mini .el-table__cell {
padding: 0 !important;
}
}
.el-table__fixed-right {
.el-table__fixed,
.el-table__fixed-right,
.el-table__fixed-left {
// 表头(深灰黑 + 纯白文字)
.el-table__fixed-header-wrapper {
th.el-table__cell {
@@ -430,35 +353,10 @@ body {
color: $--color-text-primary;
font-weight: 600;
border-bottom: 1px solid $--border-color-lighter;
padding: 4px !important; // 紧凑 padding
padding: 0 !important; // 紧凑 padding
font-size: 13px;
}
}
// 表体(奇偶行交替 + hover高亮
.el-table__fixed-body-wrapper {
.el-table__row {
// 奇数行
&:nth-child(odd) .el-table__cell {
background: $--color-background-light;
color: $--color-text-regular;
}
// 偶数行
&:nth-child(even) .el-table__cell {
background: $--color-background-light;
color: $--color-text-regular;
}
// 当前行
&.current-row .el-table__cell {
background: rgba($--color-primary, 0.35);
color: $--color-text-primary;
font-weight: 600;
}
}
}
}
// ---------------------- 3.2 日期范围选择器 ----------------------

View File

@@ -0,0 +1,79 @@
<template>
<div>
<el-select v-model="innerValue" placeholder="请选择" v-if="orderId" clearable>
<el-option
v-for="item in options"
:key="item.itemId"
:label="item.materialTypeCode + '[' + item.specification + ']'"
:value="item.itemId"
/>
</el-select>
<!-- <div v-else-if="loading" style="border: 1px solid #828991; padding: 1px;">
加载中...
</div> -->
<div v-else v-loading="loading" style="border: 1px solid #828991; padding: 1px;">请先选择订单后再选择明细</div>
</div>
</template>
<script>
import { listPurchaseOrderItem } from '@/api/erp/purchase'
export default {
props: {
orderId: {
type: String,
default: () => ''
},
value: {
type: String,
default: () => ''
}
},
data() {
return {
options: [],
loading: false
}
},
computed: {
innerValue: {
get() {
return this.value
},
set(val) {
this.$emit('input', val)
}
}
},
methods: {
loadItems() {
if (!this.orderId) {
return
}
this.loading = true
listPurchaseOrderItem({
orderId: this.orderId,
pageSize: 9999,
}).then(res => {
this.loading = false
if (res.code === 200) {
this.options = res.rows || []
}
}).catch(error => {
this.loading = false
console.error('订单明细搜索失败:', error)
})
}
},
watch: {
orderId: {
handler(newVal, oldVal) {
if (newVal) {
this.loadItems()
}
},
immediate: true
}
}
}
</script>

View File

@@ -0,0 +1,82 @@
<template>
<el-select
v-model="innerValue"
filterable
remote
reserve-keyword
placeholder="输入订单号搜索"
:remote-method="remoteMethod"
:loading="loading"
>
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</template>
<script>
import { listPurchaseOrder } from '@/api/erp/purchase'
export default {
props: {
value: {
type: String,
default: ''
}
},
data() {
return {
// innerValue: this.value, // 内部维护的选中值
options: [],
loading: false
}
},
computed: {
// 计算属性,将内部值同步到父组件
innerValue: {
get() {
return this.value
},
set(val) {
this.$emit('input', val)
}
}
},
// watch: {
// // 监听父组件传入的value变化同步到内部值
// value(newVal) {
// this.innerValue = newVal
// },
// // 监听内部值变化,同步到父组件
// innerValue(newVal) {
// this.$emit('input', newVal)
// }
// },
methods: {
remoteMethod(query) {
if (query !== '') {
this.loading = true
listPurchaseOrder({
pageNum: 1,
pageSize: 10,
orderCode: query
}).then(res => {
this.loading = false
this.options = res.rows.map(item => ({
value: item.orderId,
label: item.orderCode
}))
}).catch(error => {
this.loading = false
console.error('订单搜索失败:', error)
})
} else {
this.options = []
}
}
}
}
</script>

View File

@@ -30,14 +30,16 @@
</div>
</header>
<el-table :data="mappingRows" border size="small" class="mapping-table">
<el-table-column label="产品ID">
<el-table-column label="产品">
<template slot-scope="scope">
<el-input v-model="scope.row.productId" placeholder="产品ID" />
<!-- <el-input v-model="scope.row.productId" placeholder="产品ID" /> -->
<ProductSelect v-model="scope.row.productId" placeholder="选择产品" />
</template>
</el-table-column>
<el-table-column label="原料ID">
<el-table-column label="原料">
<template slot-scope="scope">
<el-input v-model="scope.row.rawMaterialId" placeholder="原料ID" />
<!-- <el-input v-model="scope.row.rawMaterialId" placeholder="原料ID" /> -->
<RawMaterialSelect v-model="scope.row.rawMaterialId" placeholder="选择原料" />
</template>
</el-table-column>
<el-table-column label="转换率">
@@ -91,7 +93,8 @@
<el-tabs v-model="activeTab" class="plain-tabs">
<el-tab-pane label="收货记录" name="receipt">
<div class="inline-filter">
<el-input v-model="receiptQuery.orderId" placeholder="订单ID" size="small" clearable />
<!-- <el-input v-model="receiptQuery.orderId" placeholder="订单ID" size="small" clearable /> -->
<OrderSelect v-model="receiptQuery.orderId" size="small" clearable />
<el-input v-model="receiptQuery.itemId" placeholder="明细ID" size="small" clearable />
<div class="filter-actions">
<el-button size="small" type="primary" @click="loadReceipts">查询</el-button>
@@ -130,7 +133,8 @@
<el-tab-pane label="退货管理" name="return">
<div class="inline-filter">
<el-input v-model="returnQuery.orderId" placeholder="订单ID" size="small" clearable />
<!-- <el-input v-model="returnQuery.orderId" placeholder="订单ID" size="small" clearable /> -->
<OrderSelect v-model="returnQuery.orderId" placeholder="选择订单" size="small" clearable />
<el-select v-model="returnQuery.status" placeholder="状态" size="small" clearable>
<el-option label="草稿" :value="0" />
<el-option label="完成" :value="1" />
@@ -226,10 +230,12 @@
<el-dialog :title="receiptDialog.title" :visible.sync="receiptDialog.visible" width="480px">
<el-form :model="receiptDialog.form" :rules="receiptRules" ref="receiptForm" label-width="100px" size="small">
<el-form-item label="订单ID" prop="orderId">
<el-input v-model="receiptDialog.form.orderId" />
<!-- <el-input v-model="receiptDialog.form.orderId" /> -->
<OrderSelect v-model="receiptDialog.form.orderId" />
</el-form-item>
<el-form-item label="明细ID" prop="itemId">
<el-input v-model="receiptDialog.form.itemId" />
<!-- <el-input v-model="receiptDialog.form.itemId" /> -->
<OrderDetailSelect v-model="receiptDialog.form.itemId" :orderId="receiptDialog.form.orderId" />
</el-form-item>
<el-form-item label="收货数量" prop="receivedQty">
<el-input-number v-model="receiptDialog.form.receivedQty" :min="0" :precision="3" />
@@ -259,10 +265,10 @@
</el-dialog>
<!-- 退货弹窗 -->
<el-dialog :title="returnDialog.title" :visible.sync="returnDialog.visible" width="500px">
<el-dialog :title="returnDialog.title" :visible.sync="returnDialog.visible" width="600px">
<el-form :model="returnDialog.form" :rules="returnRules" ref="returnForm" label-width="100px" size="small">
<el-form-item label="订单ID" prop="orderId">
<el-input v-model="returnDialog.form.orderId" />
<OrderSelect v-model="returnDialog.form.orderId" placeholder="选择订单" size="small" clearable />
</el-form-item>
<el-form-item label="退货类型">
<el-select v-model="returnDialog.form.returnType" clearable>
@@ -292,10 +298,11 @@
</el-dialog>
<!-- 退货明细弹窗 -->
<el-dialog :title="returnItemDialog.title" :visible.sync="returnItemDialog.visible" width="520px">
<el-dialog :title="returnItemDialog.title" :visible.sync="returnItemDialog.visible" width="600px">
<div class="toolbar">
<el-input v-model="returnItemQuery.returnId" placeholder="退货单ID" size="small" clearable class="toolbar-input" />
<el-input v-model="returnItemQuery.itemId" placeholder="订单明细ID" size="small" clearable class="toolbar-input" />
<OrderSelect v-model="returnItemQuery.orderId" />
<OrderDetailSelect v-model="returnItemQuery.itemId" :orderId="returnItemQuery.orderId" placeholder="选择订单明细" size="small" clearable />
<el-button size="small" type="primary" @click="loadReturnItems">查询</el-button>
<el-button size="small" @click="resetReturnItemQuery">重置</el-button>
<div class="toolbar-spacer"></div>
@@ -328,8 +335,11 @@
<el-form-item label="退货单ID" prop="returnId">
<el-input v-model="returnItemFormDialog.form.returnId" />
</el-form-item>
<el-form-item label="订单ID" prop="orderId">
<OrderSelect v-model="returnItemFormDialog.form.orderId" placeholder="选择订单" size="small" clearable />
</el-form-item>
<el-form-item label="订单明细ID" prop="itemId">
<el-input v-model="returnItemFormDialog.form.itemId" />
<OrderDetailSelect v-model="returnItemFormDialog.form.itemId" :orderId="returnItemFormDialog.form.orderId" placeholder="选择订单明细" size="small" clearable />
</el-form-item>
<el-form-item label="退货数量" prop="returnQty">
<el-input-number v-model="returnItemFormDialog.form.returnQty" :min="0" :precision="3" />
@@ -368,9 +378,19 @@ import {
getPurchasePriceTrend,
getSupplierQuality
} from '@/api/erp/purchase'
import RawMaterialSelect from '@/components/KLPService/RawMaterialSelect'
import ProductSelect from '@/components/KLPService/ProductSelect'
import OrderSelect from '@/components/KLPService/OrderSelect'
import OrderDetailSelect from '@/components/KLPService/OrderDetailSelect'
export default {
name: 'ErpPurchaseWorkbench',
components: {
RawMaterialSelect,
ProductSelect,
OrderSelect,
OrderDetailSelect,
},
data() {
return {
mappingRows: [{ productId: '', rawMaterialId: '', conversionRate: 1 }],
@@ -585,6 +605,7 @@ export default {
// 退货明细
openReturnItemDialog() {
this.returnItemDialog.visible = true
this.loadReturnItems()
},
loadReturnItems() {
@@ -607,7 +628,7 @@ export default {
this.returnItemFormDialog.form = { ...row }
this.returnItemFormDialog.title = '编辑退货明细'
} else {
this.returnItemFormDialog.form = { returnId: '', itemId: '', returnQty: 0 }
this.returnItemFormDialog.form = { returnId: '', itemId: '', returnQty: 0, orderId: row.orderId }
this.returnItemFormDialog.title = '新增退货明细'
}
this.returnItemFormDialog.visible = true

View File

@@ -6,8 +6,10 @@
<el-button type="primary" size="small" @click="openDialog()">新增收货</el-button>
</header>
<div class="inline-filter">
<el-input v-model="query.orderId" placeholder="订单ID" size="small" clearable />
<el-input v-model="query.itemId" placeholder="订单明细ID" size="small" clearable />
<!-- <el-input v-model="query.orderId" placeholder="订单ID" size="small" clearable /> -->
<OrderSelect v-model="query.orderId" placeholder="订单" size="small" />
<!-- <el-input v-model="query.itemId" placeholder="订单明细ID" size="small" clearable /> -->
<OrderDetailSelect :orderId="query.orderId" v-model="query.itemId"></OrderDetailSelect>
<el-select v-model="query.quality" placeholder="质检结果" size="small" clearable>
<el-option label="合格" value="OK" />
<el-option label="不合格" value="NG" />
@@ -62,10 +64,12 @@
<el-dialog :title="dialog.title" :visible.sync="dialog.visible" width="480px">
<el-form :model="dialog.form" :rules="rules" ref="form" label-width="100px" size="small">
<el-form-item label="订单ID" prop="orderId">
<el-input v-model="dialog.form.orderId" />
<!-- <el-input v-model="dialog.form.orderId" /> -->
<OrderSelect v-model="dialog.form.orderId" placeholder="订单号" size="small" />
</el-form-item>
<el-form-item label="明细ID" prop="itemId">
<el-input v-model="dialog.form.itemId" />
<!-- <el-input v-model="dialog.form.itemId" /> -->
<OrderDetailSelect :orderId="dialog.form.orderId" v-model="dialog.form.itemId"></OrderDetailSelect>
</el-form-item>
<el-form-item label="收货数量" prop="receivedQty">
<el-input-number v-model="dialog.form.receivedQty" :min="0" :precision="3" />
@@ -98,9 +102,15 @@ import {
updatePurchaseReceipt,
delPurchaseReceipt
} from '@/api/erp/purchase'
import OrderSelect from '@/components/KLPService/OrderSelect'
import OrderDetailSelect from '@/components/KLPService/OrderDetailSelect'
export default {
name: 'ErpPurchaseReceipt',
components: {
OrderSelect,
OrderDetailSelect
},
data() {
return {
query: { pageNum: 1, pageSize: 10, orderId: null, itemId: null },

View File

@@ -9,14 +9,16 @@
</div>
</header>
<el-table :data="mappingRows" border size="small" class="mapping-table">
<el-table-column label="产品ID">
<el-table-column label="产品">
<template slot-scope="scope">
<el-input v-model="scope.row.productId" placeholder="产品ID" />
<!-- <el-input v-model="scope.row.productId" placeholder="产品ID" /> -->
<ProductSelect v-model="scope.row.productId" placeholder="选择产品" />
</template>
</el-table-column>
<el-table-column label="原料ID">
<el-table-column label="原料">
<template slot-scope="scope">
<el-input v-model="scope.row.rawMaterialId" placeholder="原料ID" />
<!-- <el-input v-model="scope.row.rawMaterialId" placeholder="原料ID" /> -->
<RawMaterialSelect v-model="scope.row.rawMaterialId" placeholder="选择原料" />
</template>
</el-table-column>
<el-table-column label="转换率">
@@ -82,9 +84,15 @@
<script>
import { analyzePurchaseRequirement } from '@/api/erp/purchase'
import RawMaterialSelect from '@/components/KLPService/RawMaterialSelect'
import ProductSelect from '@/components/KLPService/ProductSelect'
export default {
name: 'ErpPurchaseRequirement',
components: {
RawMaterialSelect,
ProductSelect
},
data() {
return {
mappingRows: [{ productId: '', rawMaterialId: '', conversionRate: 1 }],

View File

@@ -6,7 +6,8 @@
<el-button type="primary" size="small" @click="openReturnDialog()">新增退货单</el-button>
</header>
<div class="inline-filter">
<el-input v-model="returnQuery.orderId" placeholder="订单ID" size="small" clearable />
<!-- <el-input v-model="returnQuery.orderId" placeholder="订单ID" size="small" clearable /> -->
<OrderSelect v-model="returnQuery.orderId" placeholder="订单ID" size="small" clearable />
<el-select v-model="returnQuery.status" placeholder="状态" size="small" clearable>
<el-option label="草稿" :value="0" />
<el-option label="完成" :value="1" />
@@ -55,7 +56,8 @@
</header>
<div class="inline-filter">
<el-input v-model="returnItemQuery.returnId" placeholder="退货单ID" size="small" clearable />
<el-input v-model="returnItemQuery.itemId" placeholder="订单明细ID" size="small" clearable />
<OrderSelect v-model="returnItemQuery.orderId" />
<OrderDetailSelect v-model="returnItemQuery.itemId" :orderId="returnItemQuery.orderId" />
<div class="filter-actions">
<el-button size="small" type="primary" @click="loadReturnItems">查询</el-button>
<el-button size="small" @click="resetReturnItemQuery">重置</el-button>
@@ -86,7 +88,8 @@
<el-dialog :title="returnDialog.title" :visible.sync="returnDialog.visible" width="520px">
<el-form :model="returnDialog.form" :rules="returnRules" ref="returnForm" label-width="100px" size="small">
<el-form-item label="订单ID" prop="orderId">
<el-input v-model="returnDialog.form.orderId" />
<!-- <el-input v-model="returnDialog.form.orderId" /> -->
<OrderSelect v-model="returnDialog.form.orderId" />
</el-form-item>
<el-form-item label="退货类型">
<el-select v-model="returnDialog.form.returnType">
@@ -121,7 +124,8 @@
<el-input v-model="returnItemDialog.form.returnId" />
</el-form-item>
<el-form-item label="订单明细ID" prop="itemId">
<el-input v-model="returnItemDialog.form.itemId" />
<!-- <el-input v-model="returnItemDialog.form.itemId" /> -->
<OrderDetailSelect v-model="returnItemDialog.form.itemId" :orderId="returnItemDialog.form.orderId" />
</el-form-item>
<el-form-item label="退货数量" prop="returnQty">
<el-input-number v-model="returnItemDialog.form.returnQty" :min="0" :precision="3" />
@@ -152,9 +156,15 @@ import {
updatePurchaseReturnItem,
delPurchaseReturnItem
} from '@/api/erp/purchase'
import OrderSelect from '@/components/KLPService/OrderSelect'
import OrderDetailSelect from '@/components/KLPService/OrderDetailSelect'
export default {
name: 'ErpPurchaseReturn',
components: {
OrderSelect,
OrderDetailSelect
},
data() {
return {
returnQuery: { pageNum: 1, pageSize: 10, orderId: null, status: null },
@@ -166,7 +176,9 @@ export default {
returnItemQuery: { pageNum: 1, pageSize: 10, returnId: null, itemId: null },
returnItemList: [],
returnItemLoading: false,
returnItemDialog: { visible: false, title: '', form: {} },
returnItemDialog: { visible: false, title: '', form: {
orderId: '',
} },
returnItemRules: {
returnId: [{ required: true, message: '请输入退货单ID', trigger: 'blur' }],
itemId: [{ required: true, message: '请输入订单明细ID', trigger: 'blur' }],
@@ -216,7 +228,9 @@ export default {
})
},
selectReturn(row) {
this.selectedReturnId = row.returnId
this.selectedReturnId = row.returnId;
this.returnItemDialog.form.orderId = row.orderId
this.returnItemQuery.orderId = row.orderId
this.openReturnItems(row)
},
openReturnItems(row) {
@@ -246,10 +260,10 @@ export default {
},
openReturnItemDialog(row) {
if (row) {
this.returnItemDialog.form = { ...row }
this.returnItemDialog.form = { ...row, orderId: this.returnItemDialog.form.orderId }
this.returnItemDialog.title = '编辑退货明细'
} else {
this.returnItemDialog.form = { returnId: this.returnItemQuery.returnId || '', itemId: '', returnQty: 0 }
this.returnItemDialog.form = { returnId: this.returnItemQuery.returnId || '', itemId: '', returnQty: 0, orderId: this.returnItemDialog.form.orderId }
this.returnItemDialog.title = '新增退货明细'
}
this.returnItemDialog.visible = true