修改采购ui
This commit is contained in:
@@ -91,7 +91,7 @@ public class ErpPurchaseOrderController extends BaseController {
|
||||
@Log(title = "采购订单主", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/{orderId}/confirm")
|
||||
public R<Void> confirm(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long orderId) {
|
||||
@PathVariable("orderId") Long orderId) {
|
||||
return toAjax(iErpPurchaseOrderService.confirmOrder(orderId, getUsername()));
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ public class ErpPurchaseOrderController extends BaseController {
|
||||
@Log(title = "采购订单主", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/{orderId}/partial")
|
||||
public R<Void> partial(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long orderId) {
|
||||
@PathVariable("orderId") Long orderId) {
|
||||
return toAjax(iErpPurchaseOrderService.markPartialArrival(orderId));
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ public class ErpPurchaseOrderController extends BaseController {
|
||||
@Log(title = "采购订单主", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/{orderId}/complete")
|
||||
public R<Void> complete(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long orderId) {
|
||||
@PathVariable("orderId") Long orderId) {
|
||||
return toAjax(iErpPurchaseOrderService.completeOrder(orderId));
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ public class ErpPurchaseOrderController extends BaseController {
|
||||
@Log(title = "采购订单主", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/{orderId}/cancel")
|
||||
public R<Void> cancel(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long orderId) {
|
||||
@PathVariable("orderId") Long orderId) {
|
||||
return toAjax(iErpPurchaseOrderService.cancelOrder(orderId));
|
||||
}
|
||||
|
||||
|
||||
@@ -319,7 +319,7 @@ body {
|
||||
background: $--table-bg;
|
||||
// border: 1px solid $--border-color-light;
|
||||
border-radius: 8px;
|
||||
box-shadow: $--metal-shadow;
|
||||
box-shadow: 0 6px 16px rgba(20, 30, 50, 0.08);
|
||||
color: $--color-text-regular;
|
||||
overflow: hidden;
|
||||
margin-top: $--form-item-margin * 2; // 与表单间距
|
||||
@@ -332,7 +332,7 @@ body {
|
||||
// 表头(深灰黑 + 纯白文字)
|
||||
.el-table__header-wrapper {
|
||||
th.el-table__cell {
|
||||
background: $--color-background;
|
||||
background: lighten($--color-background, 6%);
|
||||
color: $--color-text-primary;
|
||||
font-weight: 600;
|
||||
border-bottom: 1px solid $--border-color-lighter;
|
||||
@@ -360,8 +360,12 @@ body {
|
||||
|
||||
// hover
|
||||
&:hover .el-table__cell {
|
||||
background: rgba($--color-primary, 0.25);
|
||||
color: #888888;
|
||||
background: rgba($--color-primary, 0.12);
|
||||
color: #4a4a4a;
|
||||
}
|
||||
&:hover .el-table__cell {
|
||||
background: rgba($--color-primary, 0.12);
|
||||
color: #4a4a4a;
|
||||
}
|
||||
|
||||
// 当前行
|
||||
@@ -408,7 +412,7 @@ body {
|
||||
}
|
||||
|
||||
&__empty-block {
|
||||
background: $--color-background;
|
||||
background: lighten($--color-background, 8%);
|
||||
}
|
||||
|
||||
// 适配尺寸类(统一紧凑)
|
||||
@@ -422,7 +426,7 @@ body {
|
||||
// 表头(深灰黑 + 纯白文字)
|
||||
.el-table__fixed-header-wrapper {
|
||||
th.el-table__cell {
|
||||
background: $--color-background;
|
||||
background: lighten($--color-background, 6%);
|
||||
color: $--color-text-primary;
|
||||
font-weight: 600;
|
||||
border-bottom: 1px solid $--border-color-lighter;
|
||||
|
||||
@@ -1,17 +1,35 @@
|
||||
<template>
|
||||
<div class="erp-order-page">
|
||||
<el-card shadow="never" class="panel-card">
|
||||
<div slot="header" class="panel-header">
|
||||
<section class="surface-panel">
|
||||
<header class="surface-header">
|
||||
<span>采购订单列表</span>
|
||||
<div>
|
||||
<el-button type="primary" size="mini" @click="openOrderDialog()">新增订单</el-button>
|
||||
<el-button size="mini" @click="openItemDialog()">维护明细</el-button>
|
||||
<div class="surface-actions">
|
||||
<el-button type="primary" size="small" @click="openOrderDialog()">新增订单</el-button>
|
||||
<el-button size="small" @click="openItemDialog()">维护明细</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="toolbar">
|
||||
<el-input v-model="orderQuery.orderCode" placeholder="订单编号" size="small" clearable class="toolbar-input" />
|
||||
<el-input v-model="orderQuery.supplierId" placeholder="供应商ID" size="small" clearable class="toolbar-input" />
|
||||
<el-select v-model="orderQuery.orderStatus" placeholder="状态" size="small" clearable class="toolbar-input">
|
||||
</header>
|
||||
<div class="inline-filter">
|
||||
<el-input v-model="orderQuery.orderCode" placeholder="订单编号" size="small" clearable />
|
||||
<el-select
|
||||
v-model="orderQuery.supplierId"
|
||||
filterable
|
||||
remote
|
||||
reserve-keyword
|
||||
:remote-method="querySuppliers"
|
||||
:loading="supplierLoading"
|
||||
placeholder="供应商"
|
||||
size="small"
|
||||
clearable
|
||||
@visible-change="handleSupplierDropdown"
|
||||
>
|
||||
<el-option
|
||||
v-for="sp in supplierOptions"
|
||||
:key="sp.supplierId"
|
||||
:label="sp.name"
|
||||
:value="sp.supplierId"
|
||||
/>
|
||||
</el-select>
|
||||
<el-select v-model="orderQuery.orderStatus" placeholder="状态" size="small" clearable>
|
||||
<el-option label="草稿" :value="0" />
|
||||
<el-option label="执行中" :value="1" />
|
||||
<el-option label="部分到货" :value="2" />
|
||||
@@ -27,16 +45,18 @@
|
||||
end-placeholder="下单结束"
|
||||
size="small"
|
||||
/>
|
||||
<el-button size="small" type="primary" @click="loadOrders">查询</el-button>
|
||||
<el-button size="small" @click="resetOrderQuery">重置</el-button>
|
||||
<div class="filter-actions">
|
||||
<el-button size="small" type="primary" @click="loadOrders">查询</el-button>
|
||||
<el-button size="small" @click="resetOrderQuery">重置</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-table :data="orderList" border stripe highlight-current-row size="small" v-loading="orderLoading">
|
||||
<el-table-column prop="orderCode" label="订单编号" width="150" fixed="left" />
|
||||
<el-table-column prop="supplierId" label="供应商ID" width="120" />
|
||||
<el-table-column prop="orderDate" label="下单日期" width="120" />
|
||||
<el-table-column prop="expectedArrival" label="期望到货" width="120" />
|
||||
<el-table-column prop="orderType" label="类型" width="120" />
|
||||
<el-table-column prop="totalAmount" label="金额" width="120" />
|
||||
<el-table-column prop="supplierId" label="供应商ID" />
|
||||
<el-table-column prop="orderDate" label="下单日期" />
|
||||
<el-table-column prop="expectedArrival" label="期望到货" />
|
||||
<el-table-column prop="orderType" label="类型" />
|
||||
<el-table-column prop="totalAmount" label="金额" />
|
||||
<el-table-column label="状态" width="120">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="statusTag(scope.row.orderStatus)" size="mini">{{ statusText(scope.row.orderStatus) }}</el-tag>
|
||||
@@ -61,44 +81,124 @@
|
||||
:limit.sync="orderQuery.pageSize"
|
||||
@pagination="loadOrders"
|
||||
/>
|
||||
</el-card>
|
||||
</section>
|
||||
|
||||
<!-- 订单弹窗 -->
|
||||
<el-dialog :title="orderDialog.title" :visible.sync="orderDialog.visible" width="600px">
|
||||
<el-form :model="orderDialog.form" :rules="orderRules" ref="orderForm" label-width="100px" size="small">
|
||||
<el-row :gutter="12">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="订单编号" prop="orderCode">
|
||||
<el-input v-model="orderDialog.form.orderCode" />
|
||||
<el-dialog :title="orderDialog.title" :visible.sync="orderDialog.visible" width="960px" class="order-dialog" @close="closeOrderDialog">
|
||||
<div class="contract-layout">
|
||||
<section class="contract-card">
|
||||
<div class="contract-card__title">基础信息</div>
|
||||
<el-form :model="orderDialog.form" :rules="orderRules" ref="orderForm" label-width="100px" size="small" class="contract-form">
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="订单编号" prop="orderCode">
|
||||
<el-input v-model="orderDialog.form.orderCode" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="订单类型">
|
||||
<el-input v-model="orderDialog.form.orderType" placeholder="如标准采购、年度合同" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="供应商" prop="supplierId">
|
||||
<el-select
|
||||
v-model="orderDialog.form.supplierId"
|
||||
filterable
|
||||
remote
|
||||
reserve-keyword
|
||||
:remote-method="querySuppliers"
|
||||
:loading="supplierLoading"
|
||||
placeholder="请选择供应商"
|
||||
@visible-change="handleSupplierDropdown"
|
||||
@change="handleSupplierChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="sp in supplierOptions"
|
||||
:key="sp.supplierId"
|
||||
:label="sp.name"
|
||||
:value="sp.supplierId"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="下单日期" prop="orderDate">
|
||||
<el-date-picker v-model="orderDialog.form.orderDate" type="date" value-format="yyyy-MM-dd" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="期望到货">
|
||||
<el-date-picker v-model="orderDialog.form.expectedArrival" type="date" value-format="yyyy-MM-dd" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="总金额">
|
||||
<el-input-number v-model="orderDialog.form.totalAmount" :min="0" :precision="2" placeholder="可选" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="备注">
|
||||
<el-input type="textarea" v-model="orderDialog.form.remark" placeholder="付款、质保、交付地点等合同条款" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="供应商ID" prop="supplierId">
|
||||
<el-input v-model="orderDialog.form.supplierId" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="下单日期" prop="orderDate">
|
||||
<el-date-picker v-model="orderDialog.form.orderDate" type="date" value-format="yyyy-MM-dd" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="期望到货">
|
||||
<el-date-picker v-model="orderDialog.form.expectedArrival" type="date" value-format="yyyy-MM-dd" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="订单类型">
|
||||
<el-input v-model="orderDialog.form.orderType" />
|
||||
</el-form-item>
|
||||
<el-form-item label="金额">
|
||||
<el-input-number v-model="orderDialog.form.totalAmount" :min="0" :precision="2" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input type="textarea" v-model="orderDialog.form.remark" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer">
|
||||
</el-form>
|
||||
</section>
|
||||
|
||||
<section class="contract-card">
|
||||
<div class="contract-card__title">
|
||||
采购明细
|
||||
<span class="subtitle" v-if="orderDialog.form.orderId">(订单号:{{ orderDialog.form.orderCode || orderDialog.form.orderId }})</span>
|
||||
</div>
|
||||
<div class="contract-card__toolbar">
|
||||
<el-select
|
||||
v-model="selectedSupplierGood"
|
||||
placeholder="从供应商价目表快速添加"
|
||||
filterable
|
||||
clearable
|
||||
:disabled="!orderDialog.form.orderId"
|
||||
@focus="ensureSupplierGoods"
|
||||
@change="handleSelectGoods"
|
||||
>
|
||||
<el-option
|
||||
v-for="good in supplierGoods"
|
||||
:key="good.materialTypeCode + '_' + (good.specification || '')"
|
||||
:label="formatGoodLabel(good)"
|
||||
:value="good.materialTypeCode"
|
||||
/>
|
||||
</el-select>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="mini"
|
||||
icon="el-icon-plus"
|
||||
:disabled="!orderDialog.form.orderId"
|
||||
@click="openItemForm(null, { orderId: orderDialog.form.orderId })"
|
||||
>
|
||||
手动新增
|
||||
</el-button>
|
||||
<span class="toolbar-tip" v-if="!orderDialog.form.orderId">请先保存订单,再维护物料明细</span>
|
||||
</div>
|
||||
<el-table
|
||||
v-loading="dialogItemLoading"
|
||||
:data="dialogItems"
|
||||
size="small"
|
||||
border
|
||||
empty-text="暂未添加物料"
|
||||
>
|
||||
<el-table-column type="index" width="50" />
|
||||
<el-table-column prop="materialTypeCode" label="物料类型" />
|
||||
<el-table-column prop="specification" label="规格" />
|
||||
<el-table-column prop="quantity" label="数量" width="120" />
|
||||
<el-table-column prop="unitPrice" label="含税单价" width="120" />
|
||||
<el-table-column label="操作" width="140">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="mini" @click="openItemForm(scope.row)">编辑</el-button>
|
||||
<el-button type="text" size="mini" class="danger" @click="handleDeleteItem(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</section>
|
||||
</div>
|
||||
<div slot="footer" class="contract-footer">
|
||||
<el-button @click="orderDialog.visible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="submitOrder">保 存</el-button>
|
||||
</div>
|
||||
@@ -106,19 +206,20 @@
|
||||
|
||||
<!-- 明细弹窗 -->
|
||||
<el-dialog :title="itemDialog.title" :visible.sync="itemDialog.visible" width="640px">
|
||||
<div class="toolbar">
|
||||
<el-input v-model="itemQuery.orderId" placeholder="订单ID" size="small" clearable class="toolbar-input" />
|
||||
<el-button size="small" type="primary" @click="loadItems">查询</el-button>
|
||||
<el-button size="small" @click="resetItemQuery">重置</el-button>
|
||||
<div class="toolbar-spacer"></div>
|
||||
<el-button type="primary" size="small" @click="openItemForm()">新增明细</el-button>
|
||||
<div class="inline-filter">
|
||||
<el-input v-model="itemQuery.orderId" placeholder="订单ID" size="small" clearable />
|
||||
<div class="filter-actions">
|
||||
<el-button size="small" type="primary" @click="loadItems">查询</el-button>
|
||||
<el-button size="small" @click="resetItemQuery">重置</el-button>
|
||||
<el-button type="primary" size="small" @click="openItemForm()">新增明细</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-table :data="itemList" border size="small" v-loading="itemLoading">
|
||||
<el-table-column prop="orderId" label="订单ID" width="120" />
|
||||
<el-table-column prop="materialTypeCode" label="物料类型" width="150" />
|
||||
<el-table-column prop="specification" label="规格" min-width="150" />
|
||||
<el-table-column prop="quantity" label="数量" width="100" />
|
||||
<el-table-column prop="unitPrice" label="单价" width="100" />
|
||||
<el-table-column prop="orderId" label="订单ID" />
|
||||
<el-table-column prop="materialTypeCode" label="物料类型" />
|
||||
<el-table-column prop="specification" label="规格" />
|
||||
<el-table-column prop="quantity" label="数量" />
|
||||
<el-table-column prop="unitPrice" label="单价" />
|
||||
<el-table-column label="操作" width="150">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="mini" @click="openItemForm(scope.row)">编辑</el-button>
|
||||
@@ -178,7 +279,9 @@ import {
|
||||
listPurchaseOrderItem,
|
||||
addPurchaseOrderItem,
|
||||
updatePurchaseOrderItem,
|
||||
delPurchaseOrderItem
|
||||
delPurchaseOrderItem,
|
||||
listSupplier,
|
||||
listSupplierPrice
|
||||
} from '@/api/erp/purchase'
|
||||
|
||||
export default {
|
||||
@@ -193,7 +296,7 @@ export default {
|
||||
orderDialog: { visible: false, title: '', form: {} },
|
||||
orderRules: {
|
||||
orderCode: [{ required: true, message: '请输入订单编号', trigger: 'blur' }],
|
||||
supplierId: [{ required: true, message: '请输入供应商ID', trigger: 'blur' }]
|
||||
supplierId: [{ required: true, message: '请选择供应商', trigger: 'change' }]
|
||||
},
|
||||
itemDialog: { visible: false, title: '订单明细' },
|
||||
itemQuery: { pageNum: 1, pageSize: 10, orderId: null },
|
||||
@@ -205,11 +308,20 @@ export default {
|
||||
orderId: [{ required: true, message: '请输入订单ID', trigger: 'blur' }],
|
||||
materialTypeCode: [{ required: true, message: '请输入物料类型', trigger: 'blur' }],
|
||||
quantity: [{ required: true, message: '请输入数量', trigger: 'blur' }]
|
||||
}
|
||||
},
|
||||
supplierOptions: [],
|
||||
supplierLoading: false,
|
||||
dialogItems: [],
|
||||
dialogItemLoading: false,
|
||||
supplierGoods: [],
|
||||
goodsLoading: false,
|
||||
selectedSupplierGood: null
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadOrders()
|
||||
// 默认加载一批供应商作为下拉初始选项
|
||||
this.querySuppliers('')
|
||||
},
|
||||
methods: {
|
||||
loadOrders() {
|
||||
@@ -228,6 +340,25 @@ export default {
|
||||
this.orderLoading = false
|
||||
})
|
||||
},
|
||||
async querySuppliers(keyword) {
|
||||
this.supplierLoading = true
|
||||
try {
|
||||
const params = {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
name: keyword || undefined
|
||||
}
|
||||
const res = await listSupplier(params)
|
||||
this.supplierOptions = res.rows || []
|
||||
} finally {
|
||||
this.supplierLoading = false
|
||||
}
|
||||
},
|
||||
handleSupplierDropdown(visible) {
|
||||
if (visible && !this.supplierOptions.length && !this.supplierLoading) {
|
||||
this.querySuppliers('')
|
||||
}
|
||||
},
|
||||
resetOrderQuery() {
|
||||
this.orderQuery = { pageNum: 1, pageSize: 10, orderCode: null, supplierId: null, orderStatus: null }
|
||||
this.orderRange = []
|
||||
@@ -237,13 +368,25 @@ export default {
|
||||
if (row) {
|
||||
this.orderDialog.form = { ...row }
|
||||
this.orderDialog.title = '编辑采购订单'
|
||||
this.loadDialogItems(row.orderId)
|
||||
if (row.supplierId) {
|
||||
this.handleSupplierChange(row.supplierId)
|
||||
}
|
||||
} else {
|
||||
this.orderDialog.form = { orderCode: '', supplierId: '', orderDate: '', orderStatus: 0 }
|
||||
this.orderDialog.title = '新增采购订单'
|
||||
this.dialogItems = []
|
||||
this.supplierGoods = []
|
||||
this.selectedSupplierGood = null
|
||||
}
|
||||
this.orderDialog.visible = true
|
||||
this.$nextTick(() => this.$refs.orderForm && this.$refs.orderForm.clearValidate())
|
||||
},
|
||||
closeOrderDialog() {
|
||||
this.dialogItems = []
|
||||
this.supplierGoods = []
|
||||
this.selectedSupplierGood = null
|
||||
},
|
||||
submitOrder() {
|
||||
this.$refs.orderForm.validate(valid => {
|
||||
if (!valid) return
|
||||
@@ -251,6 +394,7 @@ export default {
|
||||
api(this.orderDialog.form).then(() => {
|
||||
this.$message.success('保存成功')
|
||||
this.orderDialog.visible = false
|
||||
this.closeOrderDialog()
|
||||
this.loadOrders()
|
||||
})
|
||||
})
|
||||
@@ -326,12 +470,24 @@ export default {
|
||||
this.itemQuery = { pageNum: 1, pageSize: 10, orderId: null }
|
||||
this.loadItems()
|
||||
},
|
||||
openItemForm(row) {
|
||||
openItemForm(row, preset = {}) {
|
||||
if (row) {
|
||||
this.itemFormDialog.form = { ...row }
|
||||
this.itemFormDialog.title = '编辑明细'
|
||||
} else {
|
||||
this.itemFormDialog.form = { orderId: '', materialTypeCode: '', quantity: 0 }
|
||||
const targetOrderId = preset.orderId || this.orderDialog.form.orderId || ''
|
||||
if (!targetOrderId) {
|
||||
this.$message.warning('请先保存订单,再新增物料')
|
||||
return
|
||||
}
|
||||
this.itemFormDialog.form = {
|
||||
orderId: targetOrderId,
|
||||
materialTypeCode: preset.materialTypeCode || '',
|
||||
specification: preset.specification || '',
|
||||
quantity: preset.quantity || 0,
|
||||
unitPrice: preset.unitPrice || 0,
|
||||
remark: preset.remark || ''
|
||||
}
|
||||
this.itemFormDialog.title = '新增明细'
|
||||
}
|
||||
this.itemFormDialog.visible = true
|
||||
@@ -345,6 +501,9 @@ export default {
|
||||
this.$message.success('保存成功')
|
||||
this.itemFormDialog.visible = false
|
||||
this.loadItems()
|
||||
if (this.orderDialog.form.orderId) {
|
||||
this.loadDialogItems(this.orderDialog.form.orderId)
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
@@ -354,7 +513,71 @@ export default {
|
||||
}).then(() => {
|
||||
this.$message.success('删除成功')
|
||||
this.loadItems()
|
||||
if (this.orderDialog.form.orderId) {
|
||||
this.loadDialogItems(this.orderDialog.form.orderId)
|
||||
}
|
||||
})
|
||||
},
|
||||
async loadDialogItems(orderId) {
|
||||
if (!orderId) {
|
||||
this.dialogItems = []
|
||||
return
|
||||
}
|
||||
this.dialogItemLoading = true
|
||||
try {
|
||||
const res = await listPurchaseOrderItem({ pageNum: 1, pageSize: 100, orderId })
|
||||
this.dialogItems = res.rows || []
|
||||
} finally {
|
||||
this.dialogItemLoading = false
|
||||
}
|
||||
},
|
||||
handleSupplierChange(val) {
|
||||
if (!val) {
|
||||
this.supplierGoods = []
|
||||
this.selectedSupplierGood = null
|
||||
return
|
||||
}
|
||||
this.selectedSupplierGood = null
|
||||
this.loadSupplierGoods(val)
|
||||
},
|
||||
ensureSupplierGoods() {
|
||||
if (!this.orderDialog.form.supplierId || this.supplierGoods.length || this.goodsLoading) return
|
||||
this.loadSupplierGoods(this.orderDialog.form.supplierId)
|
||||
},
|
||||
async loadSupplierGoods(supplierId) {
|
||||
if (!supplierId) return
|
||||
this.goodsLoading = true
|
||||
try {
|
||||
const res = await listSupplierPrice({ pageNum: 1, pageSize: 50, supplierId })
|
||||
this.supplierGoods = res.rows || []
|
||||
} finally {
|
||||
this.goodsLoading = false
|
||||
}
|
||||
},
|
||||
handleSelectGoods(code) {
|
||||
if (!code) return
|
||||
if (!this.orderDialog.form.orderId) {
|
||||
this.$message.warning('请先保存订单,再添加物料')
|
||||
this.selectedSupplierGood = null
|
||||
return
|
||||
}
|
||||
const good = this.supplierGoods.find(item => item.materialTypeCode === code)
|
||||
if (!good) return
|
||||
this.openItemForm(null, {
|
||||
orderId: this.orderDialog.form.orderId,
|
||||
materialTypeCode: good.materialTypeCode,
|
||||
specification: good.specification,
|
||||
unitPrice: good.price || 0
|
||||
})
|
||||
this.$nextTick(() => {
|
||||
this.selectedSupplierGood = null
|
||||
})
|
||||
},
|
||||
formatGoodLabel(good) {
|
||||
if (!good) return ''
|
||||
const spec = good.specification ? ` / ${good.specification}` : ''
|
||||
const price = good.price != null ? ` · ¥${good.price}` : ''
|
||||
return `${good.materialTypeCode}${spec}${price}`
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -363,32 +586,84 @@ export default {
|
||||
<style lang="scss" scoped>
|
||||
.erp-order-page {
|
||||
padding: 16px;
|
||||
background: #eef1f3;
|
||||
min-height: 100%;
|
||||
}
|
||||
.panel-card {
|
||||
border: 1px solid #d0d5d8;
|
||||
.surface-panel {
|
||||
background: #fff;
|
||||
border: 1px solid #d6dce1;
|
||||
border-radius: 4px;
|
||||
padding: 16px;
|
||||
}
|
||||
.panel-header {
|
||||
.surface-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-weight: 600;
|
||||
color: #1f2d3d;
|
||||
}
|
||||
.toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #1e2c39;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.surface-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
.inline-filter {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
.toolbar-input {
|
||||
width: 150px;
|
||||
margin-right: 8px;
|
||||
margin-bottom: 6px;
|
||||
gap: 8px;
|
||||
margin-bottom: 12px;
|
||||
> *:not(.filter-actions) {
|
||||
flex: 1 1 150px;
|
||||
}
|
||||
.filter-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
}
|
||||
.toolbar-spacer {
|
||||
flex: 1;
|
||||
.danger {
|
||||
color: #c0392b;
|
||||
}
|
||||
.order-dialog ::v-deep .el-dialog {
|
||||
max-width: 960px;
|
||||
}
|
||||
.contract-layout {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
.contract-card {
|
||||
border: 1px solid #d6dce1;
|
||||
border-radius: 4px;
|
||||
padding: 16px;
|
||||
background: #fff;
|
||||
}
|
||||
.contract-card__title {
|
||||
font-weight: 600;
|
||||
font-size: 15px;
|
||||
color: #1f2d3d;
|
||||
margin-bottom: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
.subtitle {
|
||||
font-size: 12px;
|
||||
color: #9099a8;
|
||||
}
|
||||
}
|
||||
.contract-card__toolbar {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
.toolbar-tip {
|
||||
font-size: 12px;
|
||||
color: #c97a1a;
|
||||
}
|
||||
.el-select {
|
||||
max-width: 320px;
|
||||
}
|
||||
}
|
||||
.contract-footer {
|
||||
text-align: right;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -1,52 +1,46 @@
|
||||
<template>
|
||||
<div class="erp-purchase-page">
|
||||
<el-row :gutter="16" class="summary-row">
|
||||
<el-col :span="6">
|
||||
<div class="summary-card">
|
||||
<section class="surface-panel metrics-panel">
|
||||
<div class="metrics-grid">
|
||||
<div class="metric">
|
||||
<p class="label">采购总金额</p>
|
||||
<p class="value">¥{{ summary.totalAmount | formatAmount }}</p>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<div class="summary-card">
|
||||
<div class="metric">
|
||||
<p class="label">计划采购量</p>
|
||||
<p class="value">{{ summary.suggestionTotal }} 吨</p>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<div class="summary-card">
|
||||
<div class="metric">
|
||||
<p class="label">待处理订单</p>
|
||||
<p class="value">{{ summary.pendingOrder }}</p>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<div class="summary-card">
|
||||
<div class="metric">
|
||||
<p class="label">供应商数量</p>
|
||||
<p class="value">{{ summary.supplierBrief.length }}</p>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-card class="panel-card" shadow="never">
|
||||
<div slot="header" class="panel-header">
|
||||
<span>采购需求分析</span>
|
||||
<div class="panel-actions">
|
||||
<el-switch v-model="persistResult" active-text="写入建议表" inactive-text="仅计算" />
|
||||
<el-button type="primary" size="mini" @click="handleAnalyze" :loading="analysisLoading">执行分析</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="surface-panel">
|
||||
<header class="surface-header">
|
||||
<span>采购需求分析</span>
|
||||
<div class="surface-actions">
|
||||
<el-switch v-model="persistResult" active-text="写入建议表" inactive-text="仅计算" />
|
||||
<el-button type="primary" size="small" @click="handleAnalyze" :loading="analysisLoading">执行分析</el-button>
|
||||
</div>
|
||||
</header>
|
||||
<el-table :data="mappingRows" border size="small" class="mapping-table">
|
||||
<el-table-column label="产品ID" width="160">
|
||||
<el-table-column label="产品ID">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.productId" placeholder="产品ID" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="原料ID" width="160">
|
||||
<el-table-column label="原料ID">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.rawMaterialId" placeholder="原料ID" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="转换率" width="140">
|
||||
<el-table-column label="转换率">
|
||||
<template slot-scope="scope">
|
||||
<el-input-number v-model="scope.row.conversionRate" :min="0" :max="1" :step="0.01" />
|
||||
</template>
|
||||
@@ -69,54 +63,55 @@
|
||||
show-summary
|
||||
:summary-method="analysisSummary"
|
||||
>
|
||||
<el-table-column label="产品" prop="productName" min-width="180">
|
||||
<el-table-column label="产品" prop="productName">
|
||||
<template slot-scope="scope">
|
||||
<div class="cell-title">{{ scope.row.productName || '-' }}</div>
|
||||
<div class="cell-sub">ID: {{ scope.row.productId || '-' }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="规格" prop="specification" min-width="140" />
|
||||
<el-table-column label="销售需求(吨)" prop="salesDemand" min-width="120" />
|
||||
<el-table-column label="成品库存/卷" min-width="140">
|
||||
<el-table-column label="规格" prop="specification" />
|
||||
<el-table-column label="销售需求(吨)" prop="salesDemand" />
|
||||
<el-table-column label="成品库存/卷">
|
||||
<template slot-scope="scope">
|
||||
<div>{{ scope.row.productStockWeight }}</div>
|
||||
<div class="cell-sub">{{ scope.row.productStockCoilCount }} 卷</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="原料折算(吨)" prop="rawStockConverted" min-width="120" />
|
||||
<el-table-column label="在途折算(吨)" prop="inTransitConverted" min-width="120" />
|
||||
<el-table-column label="待下达折算(吨)" prop="pendingConverted" min-width="120" />
|
||||
<el-table-column label="建议采购(吨)" prop="suggestedPurchase" min-width="120" />
|
||||
<el-table-column label="原料折算(吨)" prop="rawStockConverted" />
|
||||
<el-table-column label="在途折算(吨)" prop="inTransitConverted" />
|
||||
<el-table-column label="待下达折算(吨)" prop="pendingConverted" />
|
||||
<el-table-column label="建议采购(吨)" prop="suggestedPurchase" />
|
||||
</el-table>
|
||||
</el-card>
|
||||
</section>
|
||||
|
||||
<el-card class="panel-card" shadow="never">
|
||||
<div slot="header" class="panel-header">
|
||||
<section class="surface-panel">
|
||||
<header class="surface-header">
|
||||
<span>执行控制</span>
|
||||
</div>
|
||||
<el-tabs v-model="activeTab" type="border-card">
|
||||
</header>
|
||||
<el-tabs v-model="activeTab" class="plain-tabs">
|
||||
<el-tab-pane label="收货记录" name="receipt">
|
||||
<div class="toolbar">
|
||||
<el-input v-model="receiptQuery.orderId" placeholder="订单ID" size="small" clearable class="toolbar-input" />
|
||||
<el-input v-model="receiptQuery.itemId" placeholder="明细ID" size="small" clearable class="toolbar-input" />
|
||||
<el-button size="small" type="primary" @click="loadReceipts">查询</el-button>
|
||||
<el-button size="small" @click="resetReceiptQuery">重置</el-button>
|
||||
<div class="toolbar-spacer"></div>
|
||||
<el-button type="primary" size="small" @click="openReceiptDialog()">新增收货</el-button>
|
||||
<div class="inline-filter">
|
||||
<el-input v-model="receiptQuery.orderId" placeholder="订单ID" 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>
|
||||
<el-button size="small" @click="resetReceiptQuery">重置</el-button>
|
||||
<el-button type="primary" size="small" @click="openReceiptDialog()">新增收货</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-table :data="receiptList" v-loading="receiptLoading" border size="small">
|
||||
<el-table-column prop="receiptId" label="ID" width="80" />
|
||||
<el-table-column prop="orderId" label="订单ID" width="100" />
|
||||
<el-table-column prop="itemId" label="明细ID" width="100" />
|
||||
<el-table-column prop="receivedQty" label="收货数量" width="100" />
|
||||
<el-table-column prop="qualityResult" label="质检结果" width="120">
|
||||
<el-table-column prop="orderId" label="订单ID" />
|
||||
<el-table-column prop="itemId" label="明细ID" />
|
||||
<el-table-column prop="receivedQty" label="收货数量" />
|
||||
<el-table-column prop="qualityResult" label="质检结果">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="scope.row.qualityResult === 'NG' ? 'danger' : 'success'" size="mini">
|
||||
{{ scope.row.qualityResult || '合格' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="receiptTime" label="收货时间" width="160" />
|
||||
<el-table-column prop="receiptTime" label="收货时间" />
|
||||
<el-table-column label="操作" width="160">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="mini" @click="openReceiptDialog(scope.row)">编辑</el-button>
|
||||
@@ -134,24 +129,25 @@
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="退货管理" name="return">
|
||||
<div class="toolbar">
|
||||
<el-input v-model="returnQuery.orderId" placeholder="订单ID" size="small" clearable class="toolbar-input" />
|
||||
<el-select v-model="returnQuery.status" placeholder="状态" size="small" clearable class="toolbar-input">
|
||||
<div class="inline-filter">
|
||||
<el-input 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" />
|
||||
</el-select>
|
||||
<el-button size="small" type="primary" @click="loadReturns">查询</el-button>
|
||||
<el-button size="small" @click="resetReturnQuery">重置</el-button>
|
||||
<div class="toolbar-spacer"></div>
|
||||
<el-button type="primary" size="small" @click="openReturnDialog()">新增退货</el-button>
|
||||
<el-button size="small" @click="openReturnItemDialog()">退货明细</el-button>
|
||||
<div class="filter-actions">
|
||||
<el-button size="small" type="primary" @click="loadReturns">查询</el-button>
|
||||
<el-button size="small" @click="resetReturnQuery">重置</el-button>
|
||||
<el-button type="primary" size="small" @click="openReturnDialog()">新增退货</el-button>
|
||||
<el-button size="small" @click="openReturnItemDialog()">退货明细</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-table :data="returnList" v-loading="returnLoading" border size="small">
|
||||
<el-table-column prop="returnId" label="退货单ID" width="120" />
|
||||
<el-table-column prop="orderId" label="订单ID" width="120" />
|
||||
<el-table-column prop="returnType" label="类型" width="120" />
|
||||
<el-table-column prop="reason" label="原因" min-width="150" />
|
||||
<el-table-column prop="status" label="状态" width="120">
|
||||
<el-table-column prop="orderId" label="订单ID" />
|
||||
<el-table-column prop="returnType" label="类型" />
|
||||
<el-table-column prop="reason" label="原因" />
|
||||
<el-table-column prop="status" label="状态" width="140">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="scope.row.status === 1 ? 'success' : 'info'" size="mini">
|
||||
{{ scope.row.status === 1 ? '完成' : '草稿' }}
|
||||
@@ -174,12 +170,12 @@
|
||||
/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-card>
|
||||
</section>
|
||||
|
||||
<el-card class="panel-card" shadow="never">
|
||||
<div slot="header" class="panel-header">
|
||||
<section class="surface-panel">
|
||||
<header class="surface-header">
|
||||
<span>采购报表</span>
|
||||
<div class="panel-actions">
|
||||
<div class="surface-actions">
|
||||
<el-date-picker
|
||||
v-model="reportRange"
|
||||
type="monthrange"
|
||||
@@ -192,45 +188,39 @@
|
||||
size="small"
|
||||
/>
|
||||
</div>
|
||||
</header>
|
||||
<div class="report-grid">
|
||||
<div class="report-card">
|
||||
<h4>供应商采购额TOP</h4>
|
||||
<el-table :data="summary.supplierBrief" size="mini" height="220" border>
|
||||
<el-table-column prop="supplierId" label="供应商ID" />
|
||||
<el-table-column prop="totalAmount" label="金额" />
|
||||
<el-table-column prop="orderCount" label="订单" width="90" />
|
||||
</el-table>
|
||||
</div>
|
||||
<div class="report-card">
|
||||
<h4>价格趋势</h4>
|
||||
<el-table :data="priceTrend" size="mini" height="220" border>
|
||||
<el-table-column prop="period" label="月份" />
|
||||
<el-table-column prop="materialCode" label="物料编码" />
|
||||
<el-table-column prop="avgPrice" label="平均含税单价" />
|
||||
</el-table>
|
||||
</div>
|
||||
<div class="report-card">
|
||||
<h4>供应商退货率</h4>
|
||||
<el-table :data="supplierQuality" size="mini" height="220" border>
|
||||
<el-table-column prop="supplierId" label="供应商ID" />
|
||||
<el-table-column prop="receivedQty" label="收货量" />
|
||||
<el-table-column prop="returnQty" label="退货量" />
|
||||
<el-table-column label="退货率">
|
||||
<template slot-scope="scope">
|
||||
{{ formatPercent(scope.row.returnRate) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="8">
|
||||
<div class="report-block">
|
||||
<h4>供应商采购额TOP</h4>
|
||||
<el-table :data="summary.supplierBrief" size="mini" height="220" border>
|
||||
<el-table-column prop="supplierId" label="供应商ID" width="120" />
|
||||
<el-table-column prop="totalAmount" label="金额" />
|
||||
<el-table-column prop="orderCount" label="订单" width="80" />
|
||||
</el-table>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="report-block">
|
||||
<h4>价格趋势</h4>
|
||||
<el-table :data="priceTrend" size="mini" height="220" border>
|
||||
<el-table-column prop="period" label="月份" width="120" />
|
||||
<el-table-column prop="materialCode" label="物料编码" width="150" />
|
||||
<el-table-column prop="avgPrice" label="平均含税单价" />
|
||||
</el-table>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="report-block">
|
||||
<h4>供应商退货率</h4>
|
||||
<el-table :data="supplierQuality" size="mini" height="220" border>
|
||||
<el-table-column prop="supplierId" label="供应商ID" width="120" />
|
||||
<el-table-column prop="receivedQty" label="收货量" />
|
||||
<el-table-column prop="returnQty" label="退货量" />
|
||||
<el-table-column label="退货率">
|
||||
<template slot-scope="scope">
|
||||
{{ formatPercent(scope.row.returnRate) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</section>
|
||||
|
||||
<!-- 收货弹窗 -->
|
||||
<el-dialog :title="receiptDialog.title" :visible.sync="receiptDialog.visible" width="480px">
|
||||
@@ -649,48 +639,54 @@ export default {
|
||||
<style lang="scss" scoped>
|
||||
.erp-purchase-page {
|
||||
padding: 16px;
|
||||
background: #eef1f3;
|
||||
min-height: 100%;
|
||||
.summary-row {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
}
|
||||
.summary-card {
|
||||
background: #fdfdfd;
|
||||
border: 1px solid #d9dee4;
|
||||
padding: 16px;
|
||||
height: 90px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
.label {
|
||||
color: #5c6b77;
|
||||
font-size: 14px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.value {
|
||||
color: #1f2d3d;
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
}
|
||||
gap: 16px;
|
||||
}
|
||||
.panel-card {
|
||||
margin-bottom: 18px;
|
||||
border: 1px solid #d0d5d8;
|
||||
.surface-panel {
|
||||
background: #fff;
|
||||
border: 1px solid #d6dce1;
|
||||
border-radius: 4px;
|
||||
padding: 16px;
|
||||
}
|
||||
.panel-header {
|
||||
.surface-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-weight: 600;
|
||||
color: #1f2d3d;
|
||||
color: #1c2b36;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.panel-actions {
|
||||
.surface-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
.metrics-panel {
|
||||
padding: 0;
|
||||
}
|
||||
.metrics-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||||
gap: 12px;
|
||||
padding: 16px;
|
||||
}
|
||||
.metric {
|
||||
border: 1px solid #d6dce1;
|
||||
padding: 12px;
|
||||
background: #f9fafb;
|
||||
.label {
|
||||
font-size: 13px;
|
||||
color: #6b7785;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.value {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: #16212b;
|
||||
}
|
||||
}
|
||||
.mapping-table {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
@@ -708,27 +704,41 @@ export default {
|
||||
color: #7c8792;
|
||||
font-size: 12px;
|
||||
}
|
||||
.toolbar {
|
||||
.inline-filter {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin-bottom: 12px;
|
||||
> *:not(.filter-actions) {
|
||||
flex: 1 1 160px;
|
||||
}
|
||||
.filter-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
.report-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
|
||||
gap: 12px;
|
||||
}
|
||||
.report-card {
|
||||
border: 1px solid #d6dce1;
|
||||
padding: 12px;
|
||||
background: #fdfdfd;
|
||||
h4 {
|
||||
margin: 0 0 8px;
|
||||
font-size: 14px;
|
||||
color: #2a313c;
|
||||
}
|
||||
}
|
||||
.plain-tabs ::v-deep .el-tabs__header {
|
||||
border-bottom: 1px solid #d6dce1;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.toolbar-input {
|
||||
width: 160px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
.toolbar-spacer {
|
||||
flex: 1;
|
||||
}
|
||||
.report-block {
|
||||
border: 1px solid #d9dee4;
|
||||
padding: 12px;
|
||||
background: #fafbfc;
|
||||
h4 {
|
||||
font-weight: 600;
|
||||
margin: 0 0 8px;
|
||||
color: #2f3c4c;
|
||||
}
|
||||
.plain-tabs ::v-deep .el-tabs__content {
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -1,38 +1,40 @@
|
||||
<template>
|
||||
<div class="erp-receipt-page">
|
||||
<el-card shadow="never" class="panel-card">
|
||||
<div slot="header" class="panel-header">
|
||||
<section class="surface-panel">
|
||||
<header class="surface-header">
|
||||
<span>收货记录</span>
|
||||
<el-button type="primary" size="mini" @click="openDialog()">新增收货</el-button>
|
||||
</div>
|
||||
<div class="toolbar">
|
||||
<el-input v-model="query.orderId" placeholder="订单ID" size="small" clearable class="toolbar-input" />
|
||||
<el-input v-model="query.itemId" placeholder="订单明细ID" size="small" clearable class="toolbar-input" />
|
||||
<el-select v-model="query.quality" placeholder="质检结果" size="small" clearable class="toolbar-input">
|
||||
<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-select v-model="query.quality" placeholder="质检结果" size="small" clearable>
|
||||
<el-option label="合格" value="OK" />
|
||||
<el-option label="不合格" value="NG" />
|
||||
</el-select>
|
||||
<el-button size="small" type="primary" @click="loadData">查询</el-button>
|
||||
<el-button size="small" @click="resetQuery">重置</el-button>
|
||||
<div class="filter-actions">
|
||||
<el-button size="small" type="primary" @click="loadData">查询</el-button>
|
||||
<el-button size="small" @click="resetQuery">重置</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-table :data="list" border size="small" v-loading="loading">
|
||||
<el-table-column prop="receiptId" label="ID" width="80" />
|
||||
<el-table-column prop="orderId" label="订单ID" width="120" />
|
||||
<el-table-column prop="itemId" label="明细ID" width="120" />
|
||||
<el-table-column prop="receivedQty" label="收货数量" width="120" />
|
||||
<el-table-column prop="qualityResult" label="质检结果" width="120">
|
||||
<el-table-column prop="orderId" label="订单ID" />
|
||||
<el-table-column prop="itemId" label="明细ID" />
|
||||
<el-table-column prop="receivedQty" label="收货数量" />
|
||||
<el-table-column prop="qualityResult" label="质检结果">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="scope.row.qualityResult === 'NG' ? 'danger' : 'success'" size="mini">
|
||||
{{ scope.row.qualityResult || 'OK' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="receiptTime" label="收货时间" width="160" />
|
||||
<el-table-column label="备注" min-width="160" prop="remark" />
|
||||
<el-table-column prop="receiptTime" label="收货时间" />
|
||||
<el-table-column label="备注" prop="remark" />
|
||||
<el-table-column label="操作" width="140">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="mini" @click="openDialog(scope.row)">编辑</el-button>
|
||||
<el-button type="text" size="mini" style="color:#c0392b" @click="handleDelete(scope.row)">删除</el-button>
|
||||
<el-button type="text" size="mini" class="danger" @click="handleDelete(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -43,19 +45,19 @@
|
||||
:limit.sync="query.pageSize"
|
||||
@pagination="loadData"
|
||||
/>
|
||||
</el-card>
|
||||
</section>
|
||||
|
||||
<el-card shadow="never" class="panel-card">
|
||||
<div slot="header" class="panel-header">
|
||||
<section class="surface-panel">
|
||||
<header class="surface-header">
|
||||
<span>到货趋势</span>
|
||||
</div>
|
||||
</header>
|
||||
<el-table :data="chartData" border size="small" height="300">
|
||||
<el-table-column prop="date" label="日期" width="140" />
|
||||
<el-table-column prop="date" label="日期" />
|
||||
<el-table-column prop="totalQty" label="累计收货(吨)" />
|
||||
<el-table-column prop="qualifiedQty" label="合格数量(吨)" />
|
||||
<el-table-column prop="ngQty" label="不合格(吨)" />
|
||||
</el-table>
|
||||
</el-card>
|
||||
</section>
|
||||
|
||||
<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">
|
||||
@@ -187,28 +189,40 @@ export default {
|
||||
<style lang="scss" scoped>
|
||||
.erp-receipt-page {
|
||||
padding: 16px;
|
||||
background: #eef1f3;
|
||||
min-height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
.panel-card {
|
||||
margin-bottom: 18px;
|
||||
border: 1px solid #d0d5d8;
|
||||
.surface-panel {
|
||||
background: #fff;
|
||||
border: 1px solid #d6dce1;
|
||||
border-radius: 4px;
|
||||
padding: 16px;
|
||||
}
|
||||
.panel-header {
|
||||
.surface-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-weight: 600;
|
||||
color: #1f2d3d;
|
||||
}
|
||||
.toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.toolbar-input {
|
||||
width: 140px;
|
||||
margin-right: 8px;
|
||||
.inline-filter {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin-bottom: 12px;
|
||||
> *:not(.filter-actions) {
|
||||
flex: 1 1 150px;
|
||||
}
|
||||
.filter-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
}
|
||||
.danger {
|
||||
color: #c0392b;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="erp-report-page">
|
||||
<el-card shadow="never" class="panel-card">
|
||||
<div slot="header" class="panel-header">
|
||||
<section class="surface-panel">
|
||||
<header class="surface-header">
|
||||
<span>采购汇总</span>
|
||||
<el-date-picker
|
||||
v-model="range"
|
||||
@@ -13,67 +13,49 @@
|
||||
end-placeholder="结束时间"
|
||||
@change="loadSummary"
|
||||
/>
|
||||
</header>
|
||||
<div class="metrics-grid">
|
||||
<div class="metric-card">
|
||||
<p class="label">采购总金额</p>
|
||||
<p class="value">¥{{ summary.totalAmount | formatMoney }}</p>
|
||||
</div>
|
||||
<div class="metric-card">
|
||||
<p class="label">供应商数量</p>
|
||||
<p class="value">{{ supplierBrief.length }}</p>
|
||||
</div>
|
||||
<div class="metric-card">
|
||||
<p class="label">最大供应商金额</p>
|
||||
<p class="value">¥{{ topSupplierAmount | formatMoney }}</p>
|
||||
</div>
|
||||
<div class="metric-card">
|
||||
<p class="label">平均订单金额</p>
|
||||
<p class="value">¥{{ avgSupplierAmount | formatMoney }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="6">
|
||||
<div class="metric-card">
|
||||
<p class="label">采购总金额</p>
|
||||
<p class="value">¥{{ summary.totalAmount | formatMoney }}</p>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<div class="metric-card">
|
||||
<p class="label">供应商数量</p>
|
||||
<p class="value">{{ supplierBrief.length }}</p>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<div class="metric-card">
|
||||
<p class="label">最大供应商金额</p>
|
||||
<p class="value">¥{{ topSupplierAmount | formatMoney }}</p>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<div class="metric-card">
|
||||
<p class="label">平均订单金额</p>
|
||||
<p class="value">¥{{ avgSupplierAmount | formatMoney }}</p>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</section>
|
||||
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="8">
|
||||
<el-card shadow="never" class="panel-card">
|
||||
<div slot="header" class="panel-header">
|
||||
<span>供应商汇总</span>
|
||||
</div>
|
||||
<section class="surface-panel">
|
||||
<div class="report-grid">
|
||||
<div class="report-card">
|
||||
<h4>供应商汇总</h4>
|
||||
<el-table :data="supplierBrief" border size="small" height="320">
|
||||
<el-table-column prop="supplierId" label="供应商ID" width="140" />
|
||||
<el-table-column prop="orderCount" label="订单数" width="100" />
|
||||
<el-table-column prop="supplierId" label="供应商ID" />
|
||||
<el-table-column prop="orderCount" label="订单数" />
|
||||
<el-table-column prop="totalAmount" label="总金额" />
|
||||
</el-table>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-card shadow="never" class="panel-card">
|
||||
<div slot="header" class="panel-header">
|
||||
<span>价格趋势</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="report-card">
|
||||
<h4>价格趋势</h4>
|
||||
<el-table :data="priceTrend" border size="small" height="320">
|
||||
<el-table-column prop="period" label="月份" width="120" />
|
||||
<el-table-column prop="materialCode" label="物料编码" width="140" />
|
||||
<el-table-column prop="period" label="月份" />
|
||||
<el-table-column prop="materialCode" label="物料编码" />
|
||||
<el-table-column prop="avgPrice" label="平均含税价" />
|
||||
</el-table>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-card shadow="never" class="panel-card">
|
||||
<div slot="header" class="panel-header">
|
||||
<span>供应商退货率</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="report-card">
|
||||
<h4>供应商退货率</h4>
|
||||
<el-table :data="supplierQuality" border size="small" height="320">
|
||||
<el-table-column prop="supplierId" label="供应商ID" width="140" />
|
||||
<el-table-column prop="supplierId" label="供应商ID" />
|
||||
<el-table-column prop="receivedQty" label="收货量" />
|
||||
<el-table-column prop="returnQty" label="退货量" />
|
||||
<el-table-column label="退货率">
|
||||
@@ -82,9 +64,9 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -154,24 +136,35 @@ export default {
|
||||
<style lang="scss" scoped>
|
||||
.erp-report-page {
|
||||
padding: 16px;
|
||||
background: #eef1f3;
|
||||
min-height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
.panel-card {
|
||||
margin-bottom: 18px;
|
||||
border: 1px solid #d0d5d8;
|
||||
.surface-panel {
|
||||
background: #fff;
|
||||
border: 1px solid #d6dce1;
|
||||
border-radius: 4px;
|
||||
padding: 16px;
|
||||
}
|
||||
.panel-header {
|
||||
.surface-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-weight: 600;
|
||||
color: #1f2d3d;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.metrics-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 12px;
|
||||
}
|
||||
.metric-card {
|
||||
border: 1px solid #d9dee4;
|
||||
padding: 16px;
|
||||
background: #fff;
|
||||
background: #f9fafb;
|
||||
border-radius: 4px;
|
||||
.label {
|
||||
color: #5b6875;
|
||||
margin-bottom: 6px;
|
||||
@@ -182,5 +175,22 @@ export default {
|
||||
color: #1f2d3d;
|
||||
}
|
||||
}
|
||||
.report-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||
gap: 12px;
|
||||
}
|
||||
.report-card {
|
||||
border: 1px solid #d9dee4;
|
||||
border-radius: 4px;
|
||||
padding: 12px;
|
||||
background: #fbfbfc;
|
||||
h4 {
|
||||
margin: 0 0 8px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #2b3440;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
<template>
|
||||
<div class="erp-requirement-page">
|
||||
<el-card shadow="never" class="panel-card">
|
||||
<div slot="header" class="panel-header">
|
||||
<section class="surface-panel">
|
||||
<header class="surface-header">
|
||||
<span>采购需求分析</span>
|
||||
<div class="panel-actions">
|
||||
<div class="surface-actions">
|
||||
<el-switch v-model="persistResult" active-text="写入建议表" inactive-text="仅计算" />
|
||||
<el-button type="primary" size="mini" @click="handleAnalyze" :loading="loading">执行分析</el-button>
|
||||
<el-button type="primary" size="small" @click="handleAnalyze" :loading="loading">执行分析</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<el-table :data="mappingRows" border size="small" class="mapping-table">
|
||||
<el-table-column label="产品ID" width="180">
|
||||
<el-table-column label="产品ID">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.productId" placeholder="产品ID" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="原料ID" width="180">
|
||||
<el-table-column label="原料ID">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.rawMaterialId" placeholder="原料ID" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="转换率" width="160">
|
||||
<el-table-column label="转换率">
|
||||
<template slot-scope="scope">
|
||||
<el-input-number v-model="scope.row.conversionRate" :min="0" :max="1" :step="0.01" />
|
||||
</template>
|
||||
@@ -40,19 +40,19 @@
|
||||
show-summary
|
||||
:summary-method="summaryMethod"
|
||||
>
|
||||
<el-table-column label="产品" width="220">
|
||||
<el-table-column label="产品">
|
||||
<template slot-scope="scope">
|
||||
<div class="title">{{ scope.row.productName || '-' }}</div>
|
||||
<div class="cell-sub">ID: {{ scope.row.productId || '-' }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="specification" label="规格" width="160" />
|
||||
<el-table-column prop="salesDemand" label="销售需求(吨)" width="140" />
|
||||
<el-table-column prop="productStockWeight" label="成品库存(吨)" width="140" />
|
||||
<el-table-column prop="rawStockConverted" label="原料折算(吨)" width="140" />
|
||||
<el-table-column prop="inTransitConverted" label="在途折算(吨)" width="140" />
|
||||
<el-table-column prop="pendingConverted" label="待下达折算(吨)" width="140" />
|
||||
<el-table-column prop="suggestedPurchase" label="建议采购(吨)" width="160">
|
||||
<el-table-column prop="specification" label="规格" />
|
||||
<el-table-column prop="salesDemand" label="销售需求(吨)" />
|
||||
<el-table-column prop="productStockWeight" label="成品库存(吨)" />
|
||||
<el-table-column prop="rawStockConverted" label="原料折算(吨)" />
|
||||
<el-table-column prop="inTransitConverted" label="在途折算(吨)" />
|
||||
<el-table-column prop="pendingConverted" label="待下达折算(吨)" />
|
||||
<el-table-column prop="suggestedPurchase" label="建议采购(吨)">
|
||||
<template slot-scope="scope">
|
||||
<span :class="scope.row.suggestedPurchase > 0 ? 'highlight' : ''">
|
||||
{{ scope.row.suggestedPurchase }}
|
||||
@@ -60,23 +60,23 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</section>
|
||||
|
||||
<el-card shadow="never" class="panel-card">
|
||||
<div slot="header" class="panel-header">
|
||||
<section class="surface-panel">
|
||||
<header class="surface-header">
|
||||
<span>原料折算详情</span>
|
||||
</div>
|
||||
</header>
|
||||
<el-table :data="rawDetailData" size="small" border height="320">
|
||||
<el-table-column prop="productName" label="产品" width="200" />
|
||||
<el-table-column prop="rawMaterialName" label="原料" width="200" />
|
||||
<el-table-column prop="conversionRate" label="转换率" width="120" />
|
||||
<el-table-column prop="stockWeight" label="库存重量" width="120" />
|
||||
<el-table-column prop="stockCoilCount" label="库存卷数" width="120" />
|
||||
<el-table-column prop="convertedStock" label="折算库存" width="120" />
|
||||
<el-table-column prop="convertedInTransit" label="折算在途" width="120" />
|
||||
<el-table-column prop="convertedPending" label="折算待下达" width="120" />
|
||||
<el-table-column prop="productName" label="产品" />
|
||||
<el-table-column prop="rawMaterialName" label="原料" />
|
||||
<el-table-column prop="conversionRate" label="转换率" />
|
||||
<el-table-column prop="stockWeight" label="库存重量" />
|
||||
<el-table-column prop="stockCoilCount" label="库存卷数" />
|
||||
<el-table-column prop="convertedStock" label="折算库存" />
|
||||
<el-table-column prop="convertedInTransit" label="折算在途" />
|
||||
<el-table-column prop="convertedPending" label="折算待下达" />
|
||||
</el-table>
|
||||
</el-card>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -161,21 +161,26 @@ export default {
|
||||
<style lang="scss" scoped>
|
||||
.erp-requirement-page {
|
||||
padding: 16px;
|
||||
background: #eef1f3;
|
||||
min-height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
.panel-card {
|
||||
margin-bottom: 18px;
|
||||
border: 1px solid #d0d5d8;
|
||||
.surface-panel {
|
||||
background: #fff;
|
||||
border: 1px solid #d6dce1;
|
||||
border-radius: 4px;
|
||||
padding: 16px;
|
||||
}
|
||||
.panel-header {
|
||||
.surface-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-weight: 600;
|
||||
color: #1f2d3d;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.panel-actions {
|
||||
.surface-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
|
||||
@@ -1,79 +1,87 @@
|
||||
<template>
|
||||
<div class="erp-return-page">
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="13">
|
||||
<el-card shadow="never" class="panel-card">
|
||||
<div slot="header" class="panel-header">
|
||||
<span>退货单</span>
|
||||
<el-button type="primary" size="mini" @click="openReturnDialog()">新增退货单</el-button>
|
||||
<section class="surface-panel">
|
||||
<header class="surface-header">
|
||||
<span>退货单</span>
|
||||
<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-select v-model="returnQuery.status" placeholder="状态" size="small" clearable>
|
||||
<el-option label="草稿" :value="0" />
|
||||
<el-option label="完成" :value="1" />
|
||||
</el-select>
|
||||
<div class="filter-actions">
|
||||
<el-button size="small" type="primary" @click="loadReturns">查询</el-button>
|
||||
<el-button size="small" @click="resetReturnQuery">重置</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="return-card-grid" v-loading="returnLoading">
|
||||
<div
|
||||
v-for="item in returnList"
|
||||
:key="item.returnId"
|
||||
class="return-card"
|
||||
:class="{ active: selectedReturnId === item.returnId }"
|
||||
@click="selectReturn(item)"
|
||||
>
|
||||
<div class="card-header">
|
||||
<div>
|
||||
<p class="title">退货单 {{ item.returnId }}</p>
|
||||
<p class="sub">订单 {{ item.orderId }}</p>
|
||||
</div>
|
||||
<el-tag :type="item.status === 1 ? 'success' : 'info'" size="mini">
|
||||
{{ item.status === 1 ? '完成' : '草稿' }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<div class="toolbar">
|
||||
<el-input v-model="returnQuery.orderId" placeholder="订单ID" size="small" clearable class="toolbar-input" />
|
||||
<el-select v-model="returnQuery.status" placeholder="状态" size="small" clearable class="toolbar-input">
|
||||
<el-option label="草稿" :value="0" />
|
||||
<el-option label="完成" :value="1" />
|
||||
</el-select>
|
||||
<el-button size="small" type="primary" @click="loadReturns">查询</el-button>
|
||||
<el-button size="small" @click="resetReturnQuery">重置</el-button>
|
||||
<div class="card-body">
|
||||
<p><span>类型</span>{{ item.returnType || '-' }}</p>
|
||||
<p><span>原因</span>{{ item.reason || '-' }}</p>
|
||||
<p><span>退货日期</span>{{ item.returnDate || '-' }}</p>
|
||||
</div>
|
||||
<el-table :data="returnList" border size="small" v-loading="returnLoading" height="420">
|
||||
<el-table-column prop="returnId" label="退货单ID" width="120" />
|
||||
<el-table-column prop="orderId" label="订单ID" width="120" />
|
||||
<el-table-column prop="returnType" label="类型" width="120" />
|
||||
<el-table-column prop="reason" label="原因" min-width="160" />
|
||||
<el-table-column prop="status" label="状态" width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="scope.row.status === 1 ? 'success' : 'info'" size="mini">
|
||||
{{ scope.row.status === 1 ? '完成' : '草稿' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="160">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="mini" @click="openReturnDialog(scope.row)">编辑</el-button>
|
||||
<el-button type="text" size="mini" @click="openReturnItems(scope.row)">明细</el-button>
|
||||
<el-button type="text" size="mini" style="color:#c0392b" @click="handleDeleteReturn(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<div class="card-actions">
|
||||
<el-button type="text" size="mini" @click.stop="openReturnDialog(item)">编辑</el-button>
|
||||
<el-button type="text" size="mini" @click.stop="openReturnItems(item)">明细</el-button>
|
||||
<el-button type="text" size="mini" class="danger" @click.stop="handleDeleteReturn(item)">删除</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-empty v-if="!returnList.length && !returnLoading" description="暂无退货单" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<el-col :span="11">
|
||||
<el-card shadow="never" class="panel-card">
|
||||
<div slot="header" class="panel-header">
|
||||
<span>退货明细</span>
|
||||
<el-button type="primary" size="mini" @click="openReturnItemDialog()">新增明细</el-button>
|
||||
</div>
|
||||
<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" />
|
||||
<el-button size="small" type="primary" @click="loadReturnItems">查询</el-button>
|
||||
<el-button size="small" @click="resetReturnItemQuery">重置</el-button>
|
||||
</div>
|
||||
<el-table :data="returnItemList" border size="small" height="420" v-loading="returnItemLoading">
|
||||
<el-table-column prop="returnItemId" label="ID" width="80" />
|
||||
<el-table-column prop="returnId" label="退货单ID" width="120" />
|
||||
<el-table-column prop="itemId" label="订单明细ID" width="150" />
|
||||
<el-table-column prop="returnQty" label="数量" width="100" />
|
||||
<el-table-column label="问题照片" min-width="140">
|
||||
<template slot-scope="scope">
|
||||
<el-tooltip v-if="scope.row.photos" :content="scope.row.photos" placement="top">
|
||||
<span class="link">查看</span>
|
||||
</el-tooltip>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="140">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="mini" @click="openReturnItemDialog(scope.row)">编辑</el-button>
|
||||
<el-button type="text" size="mini" style="color:#c0392b" @click="handleDeleteReturnItem(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<section class="surface-panel">
|
||||
<header class="surface-header">
|
||||
<span>退货明细</span>
|
||||
<el-button type="primary" size="small" @click="openReturnItemDialog()">新增明细</el-button>
|
||||
</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 />
|
||||
<div class="filter-actions">
|
||||
<el-button size="small" type="primary" @click="loadReturnItems">查询</el-button>
|
||||
<el-button size="small" @click="resetReturnItemQuery">重置</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-table :data="returnItemList" border size="small" v-loading="returnItemLoading">
|
||||
<el-table-column prop="returnItemId" label="ID" width="80" />
|
||||
<el-table-column prop="returnId" label="退货单ID" />
|
||||
<el-table-column prop="itemId" label="订单明细ID" />
|
||||
<el-table-column prop="returnQty" label="数量" />
|
||||
<el-table-column label="问题照片">
|
||||
<template slot-scope="scope">
|
||||
<el-tooltip v-if="scope.row.photos" :content="scope.row.photos" placement="top">
|
||||
<span class="link">查看</span>
|
||||
</el-tooltip>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="150">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="mini" @click="openReturnItemDialog(scope.row)">编辑</el-button>
|
||||
<el-button type="text" size="mini" class="danger" @click="handleDeleteReturnItem(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</section>
|
||||
|
||||
<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">
|
||||
@@ -152,6 +160,7 @@ export default {
|
||||
returnQuery: { pageNum: 1, pageSize: 10, orderId: null, status: null },
|
||||
returnList: [],
|
||||
returnLoading: false,
|
||||
selectedReturnId: null,
|
||||
returnDialog: { visible: false, title: '', form: {} },
|
||||
returnRules: { orderId: [{ required: true, message: '请输入订单ID', trigger: 'blur' }] },
|
||||
returnItemQuery: { pageNum: 1, pageSize: 10, returnId: null, itemId: null },
|
||||
@@ -206,7 +215,12 @@ export default {
|
||||
})
|
||||
})
|
||||
},
|
||||
selectReturn(row) {
|
||||
this.selectedReturnId = row.returnId
|
||||
this.openReturnItems(row)
|
||||
},
|
||||
openReturnItems(row) {
|
||||
this.selectedReturnId = row.returnId
|
||||
this.returnItemQuery.returnId = row.returnId
|
||||
this.loadReturnItems()
|
||||
},
|
||||
@@ -265,27 +279,93 @@ export default {
|
||||
<style lang="scss" scoped>
|
||||
.erp-return-page {
|
||||
padding: 16px;
|
||||
background: #eef1f3;
|
||||
min-height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
.panel-card {
|
||||
border: 1px solid #d0d5d8;
|
||||
margin-bottom: 16px;
|
||||
.surface-panel {
|
||||
background: #fff;
|
||||
border: 1px solid #d6dce1;
|
||||
border-radius: 4px;
|
||||
padding: 16px;
|
||||
}
|
||||
.panel-header {
|
||||
.surface-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-weight: 600;
|
||||
}
|
||||
.toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #1e2c39;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.toolbar-input {
|
||||
width: 140px;
|
||||
margin-right: 8px;
|
||||
.inline-filter {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin-bottom: 12px;
|
||||
> *:not(.filter-actions) {
|
||||
flex: 1 1 160px;
|
||||
}
|
||||
.filter-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
}
|
||||
.return-card-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
|
||||
gap: 12px;
|
||||
}
|
||||
.return-card {
|
||||
border: 1px solid #d6dce1;
|
||||
border-radius: 4px;
|
||||
padding: 12px;
|
||||
background: #fbfbfc;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
cursor: pointer;
|
||||
transition: transform 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
|
||||
&.active {
|
||||
border-color: #409eff;
|
||||
transform: scale(1.02);
|
||||
box-shadow: 0 6px 20px rgba(16, 38, 70, 0.08);
|
||||
}
|
||||
}
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
.title {
|
||||
margin: 0;
|
||||
font-weight: 600;
|
||||
color: #15202b;
|
||||
}
|
||||
.sub {
|
||||
margin: 2px 0 0;
|
||||
color: #7a8699;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
.card-body {
|
||||
p {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 13px;
|
||||
color: #4a5663;
|
||||
margin: 0;
|
||||
span {
|
||||
color: #98a1ac;
|
||||
}
|
||||
}
|
||||
}
|
||||
.card-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 8px;
|
||||
.danger {
|
||||
color: #c0392b;
|
||||
}
|
||||
}
|
||||
.link {
|
||||
color: #2f86d7;
|
||||
|
||||
@@ -1,82 +1,99 @@
|
||||
<template>
|
||||
<div class="erp-supplier-page">
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="10">
|
||||
<el-card shadow="never" class="panel-card">
|
||||
<div slot="header" class="panel-header">
|
||||
<span>供应商档案</span>
|
||||
<el-button type="primary" size="mini" @click="openSupplierDialog()">新增</el-button>
|
||||
<section class="surface-panel supplier-panel">
|
||||
<header class="surface-header">
|
||||
<span>供应商档案</span>
|
||||
<el-button type="primary" size="small" @click="openSupplierDialog()">新增</el-button>
|
||||
</header>
|
||||
<div class="inline-filter">
|
||||
<el-input v-model="supplierQuery.name" placeholder="供应商名称" size="small" clearable />
|
||||
<el-select v-model="supplierQuery.creditRating" placeholder="信用等级" size="small" clearable>
|
||||
<el-option label="A" value="A" />
|
||||
<el-option label="B" value="B" />
|
||||
<el-option label="C" value="C" />
|
||||
<el-option label="D" value="D" />
|
||||
</el-select>
|
||||
<div class="filter-actions">
|
||||
<el-button size="small" type="primary" @click="loadSuppliers">查询</el-button>
|
||||
<el-button size="small" @click="resetSupplierQuery">重置</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="supplier-grid" v-loading="supplierLoading">
|
||||
<div
|
||||
v-for="item in supplierList"
|
||||
:key="item.supplierId"
|
||||
class="supplier-card"
|
||||
>
|
||||
<div class="card-head">
|
||||
<div>
|
||||
<p class="title">{{ item.name }}</p>
|
||||
<p class="sub">编码:{{ item.supplierCode || '-' }}</p>
|
||||
</div>
|
||||
<div class="tag-group">
|
||||
<el-tag size="mini" type="info">{{ supplierTypeLabel(item.type) }}</el-tag>
|
||||
<el-tag size="mini" type="plain">信用 {{ item.creditRating || '-' }}</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
<div class="toolbar">
|
||||
<el-input v-model="supplierQuery.name" placeholder="供应商名称" size="small" clearable class="toolbar-input" />
|
||||
<el-select v-model="supplierQuery.creditRating" placeholder="信用等级" size="small" clearable class="toolbar-input">
|
||||
<el-option label="A" value="A" />
|
||||
<el-option label="B" value="B" />
|
||||
<el-option label="C" value="C" />
|
||||
<el-option label="D" value="D" />
|
||||
</el-select>
|
||||
<el-button size="small" type="primary" @click="loadSuppliers">查询</el-button>
|
||||
<el-button size="small" @click="resetSupplierQuery">重置</el-button>
|
||||
<ul class="card-body">
|
||||
<li><span>联系人</span><strong>{{ item.contactPerson || '-' }}</strong></li>
|
||||
<li><span>电话</span><strong>{{ item.contactPhone || '-' }}</strong></li>
|
||||
<li><span>地址</span><strong>{{ item.address || '-' }}</strong></li>
|
||||
<li><span>备注</span><strong>{{ item.remark || '-' }}</strong></li>
|
||||
</ul>
|
||||
<div class="card-actions">
|
||||
<el-button type="text" size="mini" @click="openSupplierDialog(item)">编辑</el-button>
|
||||
<el-button type="text" size="mini" @click="openPriceDrawer(item)">价格</el-button>
|
||||
<el-button type="text" size="mini" class="danger" @click="handleDeleteSupplier(item)">删除</el-button>
|
||||
</div>
|
||||
<el-table :data="supplierList" height="420" size="small" border v-loading="supplierLoading">
|
||||
<el-table-column prop="supplierCode" label="编码" width="120" />
|
||||
<el-table-column prop="name" label="名称" min-width="160" />
|
||||
<el-table-column prop="creditRating" label="信用" width="80" />
|
||||
<el-table-column label="联系人" width="140">
|
||||
<template slot-scope="scope">
|
||||
<div>{{ scope.row.contactPerson || '-' }}</div>
|
||||
<div class="cell-sub">{{ scope.row.contactPhone || '' }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="160">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="mini" @click="openSupplierDialog(scope.row)">编辑</el-button>
|
||||
<el-button type="text" size="mini" @click="handleDeleteSupplier(scope.row)" style="color:#c0392b">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="14">
|
||||
<el-card shadow="never" class="panel-card">
|
||||
<div slot="header" class="panel-header">
|
||||
<span>供应商价格表</span>
|
||||
<el-button type="primary" size="mini" @click="openPriceDialog()">新增价格</el-button>
|
||||
</div>
|
||||
<el-empty v-if="!supplierList.length && !supplierLoading" description="暂无数据" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<el-drawer
|
||||
title="供应商价格表"
|
||||
:visible.sync="priceDrawer.visible"
|
||||
size="480px"
|
||||
direction="rtl"
|
||||
append-to-body
|
||||
custom-class="price-drawer"
|
||||
@close="closePriceDrawer"
|
||||
>
|
||||
<div class="price-drawer-body">
|
||||
<div class="drawer-header" v-if="priceDrawer.supplier">
|
||||
<div class="drawer-title-block">
|
||||
<p class="drawer-title">{{ priceDrawer.supplier.name }}</p>
|
||||
<p class="drawer-sub">编码:{{ priceDrawer.supplier.supplierCode || '-' }}</p>
|
||||
</div>
|
||||
<div class="toolbar">
|
||||
<el-input v-model="priceQuery.materialTypeCode" placeholder="物料编码" size="small" clearable class="toolbar-input" />
|
||||
<el-select v-model="priceQuery.supplierId" placeholder="供应商" size="small" clearable class="toolbar-input">
|
||||
<el-option v-for="sp in supplierOptions" :key="sp.supplierId" :label="sp.name" :value="sp.supplierId" />
|
||||
</el-select>
|
||||
<el-date-picker v-model="priceRange" type="daterange" value-format="yyyy-MM-dd" size="small" range-separator="至"
|
||||
start-placeholder="生效日期" end-placeholder="失效日期" />
|
||||
<el-button size="small" type="primary" @click="loadPrices">查询</el-button>
|
||||
</div>
|
||||
<el-table :data="priceList" size="small" border v-loading="priceLoading">
|
||||
<el-table-column prop="supplierId" label="供应商" width="150">
|
||||
<template slot-scope="scope">
|
||||
{{ matchSupplier(scope.row.supplierId) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="materialTypeCode" label="物料类型" width="160" />
|
||||
<el-table-column prop="specification" label="规格" min-width="140" />
|
||||
<el-table-column prop="price" label="价格(含税)" width="110" />
|
||||
<el-table-column label="有效期" width="200">
|
||||
<template slot-scope="scope">
|
||||
<div>{{ scope.row.validFrom || '-' }}</div>
|
||||
<div class="cell-sub">{{ scope.row.validTo || '-' }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="160">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="mini" @click="openPriceDialog(scope.row)">编辑</el-button>
|
||||
<el-button type="text" size="mini" @click="handleDeletePrice(scope.row)" style="color:#c0392b">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-button type="primary" size="mini" @click="openPriceDialog()">新增价格</el-button>
|
||||
</div>
|
||||
|
||||
<div class="drawer-section">
|
||||
<div class="drawer-section-title">价格列表</div>
|
||||
<el-collapse v-model="activePricePanels" accordion>
|
||||
<el-collapse-item
|
||||
v-for="item in priceList"
|
||||
:name="item.priceId"
|
||||
:title="`${item.materialTypeCode || '未指定'} · ¥${item.price || 0}`"
|
||||
:key="item.priceId"
|
||||
>
|
||||
<ul class="price-info">
|
||||
<li><span>规格</span>{{ item.specification || '-' }}</li>
|
||||
<li><span>含税价</span>{{ item.price || '-' }}</li>
|
||||
<li><span>有效期</span>{{ formatRange(item.validFrom, item.validTo) }}</li>
|
||||
<li><span>备注</span>{{ item.remark || '-' }}</li>
|
||||
</ul>
|
||||
<div class="price-actions">
|
||||
<el-button type="text" size="mini" @click="openPriceDialog(item)">编辑</el-button>
|
||||
<el-button type="text" size="mini" class="danger" @click="handleDeletePrice(item)">删除</el-button>
|
||||
</div>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
<el-empty v-if="!priceList.length && !priceLoading" description="暂无价格记录" />
|
||||
<el-skeleton v-if="priceLoading" animated rows="4" />
|
||||
</div>
|
||||
</div>
|
||||
</el-drawer>
|
||||
|
||||
<!-- 供应商弹窗 -->
|
||||
<el-dialog :title="supplierDialog.title" :visible.sync="supplierDialog.visible" width="520px">
|
||||
@@ -87,8 +104,10 @@
|
||||
<el-form-item label="名称" prop="name">
|
||||
<el-input v-model="supplierDialog.form.name" />
|
||||
</el-form-item>
|
||||
<el-form-item label="类型">
|
||||
<el-input v-model="supplierDialog.form.type" />
|
||||
<el-form-item label="类型" prop="type">
|
||||
<el-select v-model="supplierDialog.form.type" placeholder="请选择类型">
|
||||
<el-option v-for="opt in supplierTypeOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="信用等级">
|
||||
<el-select v-model="supplierDialog.form.creditRating" clearable>
|
||||
@@ -125,11 +144,14 @@
|
||||
<el-option v-for="sp in supplierOptions" :key="sp.supplierId" :label="sp.name" :value="sp.supplierId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="物料类型" prop="materialTypeCode">
|
||||
<el-input v-model="priceDialog.form.materialTypeCode" />
|
||||
<el-form-item label="原料" prop="rawMaterialId">
|
||||
<RawMaterialSelect v-model="priceDialog.form.rawMaterialId" @change="handleMaterialChange" />
|
||||
</el-form-item>
|
||||
<el-form-item label="物料编码">
|
||||
<el-input v-model="priceDialog.form.materialTypeCode" placeholder="选择原料后自动带出" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="规格">
|
||||
<el-input v-model="priceDialog.form.specification" />
|
||||
<el-input v-model="priceDialog.form.specification" placeholder="选择原料后可调整" />
|
||||
</el-form-item>
|
||||
<el-form-item label="含税价格" prop="price">
|
||||
<el-input-number v-model="priceDialog.form.price" :min="0" :precision="2" />
|
||||
@@ -166,31 +188,39 @@ import {
|
||||
updateSupplierPrice,
|
||||
delSupplierPrice
|
||||
} from '@/api/erp/purchase'
|
||||
import RawMaterialSelect from '@/components/KLPService/RawMaterialSelect'
|
||||
|
||||
export default {
|
||||
name: 'ErpSupplierManage',
|
||||
components: { RawMaterialSelect },
|
||||
data() {
|
||||
return {
|
||||
supplierTypeOptions: [
|
||||
{ label: '原料供应商', value: 'RAW' },
|
||||
{ label: '其他供应商', value: 'OTHER' }
|
||||
],
|
||||
supplierQuery: { pageNum: 1, pageSize: 50, name: null, creditRating: null },
|
||||
supplierList: [],
|
||||
supplierLoading: false,
|
||||
supplierDialog: { visible: false, title: '', form: {} },
|
||||
supplierRules: {
|
||||
supplierCode: [{ required: true, message: '请输入编码', trigger: 'blur' }],
|
||||
name: [{ required: true, message: '请输入名称', trigger: 'blur' }]
|
||||
name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
|
||||
type: [{ required: true, message: '请选择类型', trigger: 'change' }]
|
||||
},
|
||||
priceQuery: { pageNum: 1, pageSize: 50, supplierId: null, materialTypeCode: null },
|
||||
priceQuery: { pageNum: 1, pageSize: 50, supplierId: null },
|
||||
priceList: [],
|
||||
priceLoading: false,
|
||||
priceDialog: { visible: false, title: '', form: {} },
|
||||
priceRules: {
|
||||
supplierId: [{ required: true, message: '请选择供应商', trigger: 'change' }],
|
||||
materialTypeCode: [{ required: true, message: '请输入物料类型', trigger: 'blur' }],
|
||||
rawMaterialId: [{ required: true, message: '请选择原料', trigger: 'change' }],
|
||||
price: [{ required: true, message: '请输入价格', trigger: 'change' }]
|
||||
},
|
||||
priceRange: [],
|
||||
priceValidRange: [],
|
||||
supplierOptions: []
|
||||
supplierOptions: [],
|
||||
priceDrawer: { visible: false, supplier: null },
|
||||
activePricePanels: []
|
||||
}
|
||||
},
|
||||
created() {
|
||||
@@ -218,7 +248,7 @@ export default {
|
||||
this.supplierDialog.form = { ...row }
|
||||
this.supplierDialog.title = '编辑供应商'
|
||||
} else {
|
||||
this.supplierDialog.form = { supplierCode: '', name: '', creditRating: 'A' }
|
||||
this.supplierDialog.form = { supplierCode: '', name: '', creditRating: 'A', type: 'RAW' }
|
||||
this.supplierDialog.title = '新增供应商'
|
||||
}
|
||||
this.supplierDialog.visible = true
|
||||
@@ -243,17 +273,31 @@ export default {
|
||||
this.loadSuppliers()
|
||||
})
|
||||
},
|
||||
supplierTypeLabel(val) {
|
||||
const target = this.supplierTypeOptions.find(opt => opt.value === val)
|
||||
return target ? target.label : '其他供应商'
|
||||
},
|
||||
// price
|
||||
openPriceDrawer(item) {
|
||||
this.priceDrawer = { visible: true, supplier: item }
|
||||
this.priceQuery = { ...this.priceQuery, supplierId: item.supplierId, pageNum: 1 }
|
||||
this.loadPrices()
|
||||
},
|
||||
closePriceDrawer() {
|
||||
this.priceDrawer.visible = false
|
||||
this.priceDrawer.supplier = null
|
||||
this.priceList = []
|
||||
},
|
||||
loadPrices() {
|
||||
const query = { ...this.priceQuery }
|
||||
if (this.priceRange && this.priceRange.length === 2) {
|
||||
query.beginTime = this.priceRange[0]
|
||||
query.endTime = this.priceRange[1]
|
||||
if (!this.priceQuery.supplierId) {
|
||||
this.priceList = []
|
||||
return
|
||||
}
|
||||
this.priceLoading = true
|
||||
listSupplierPrice(query)
|
||||
listSupplierPrice(this.priceQuery)
|
||||
.then(res => {
|
||||
this.priceList = res.rows || []
|
||||
this.activePricePanels = (this.priceList[0] && [this.priceList[0].priceId]) || []
|
||||
})
|
||||
.finally(() => {
|
||||
this.priceLoading = false
|
||||
@@ -273,7 +317,8 @@ export default {
|
||||
this.priceValidRange = [row.validFrom, row.validTo]
|
||||
this.priceDialog.title = '编辑价格'
|
||||
} else {
|
||||
this.priceDialog.form = { supplierId: null, materialTypeCode: '', price: 0 }
|
||||
const currentSupplierId = this.priceDrawer.supplier?.supplierId || null
|
||||
this.priceDialog.form = { supplierId: currentSupplierId, rawMaterialId: '', materialTypeCode: '', specification: '', price: 0 }
|
||||
this.priceValidRange = []
|
||||
this.priceDialog.title = '新增价格'
|
||||
}
|
||||
@@ -287,6 +332,10 @@ export default {
|
||||
this.priceDialog.form.validFrom = this.priceValidRange[0]
|
||||
this.priceDialog.form.validTo = this.priceValidRange[1]
|
||||
}
|
||||
if (!this.priceDialog.form.materialTypeCode) {
|
||||
this.$message.warning('请先选择原料')
|
||||
return
|
||||
}
|
||||
const api = this.priceDialog.form.priceId ? updateSupplierPrice : addSupplierPrice
|
||||
api(this.priceDialog.form).then(() => {
|
||||
this.$message.success('保存成功')
|
||||
@@ -302,6 +351,18 @@ export default {
|
||||
this.$message.success('删除成功')
|
||||
this.loadPrices()
|
||||
})
|
||||
},
|
||||
handleMaterialChange(val, rows) {
|
||||
const target = Array.isArray(rows) ? rows[0] : null
|
||||
this.priceDialog.form.rawMaterialId = val
|
||||
if (target) {
|
||||
this.priceDialog.form.materialTypeCode = target.rawMaterialCode
|
||||
this.priceDialog.form.specification = target.specification
|
||||
}
|
||||
},
|
||||
formatRange(start, end) {
|
||||
if (!start && !end) return '-'
|
||||
return `${start || '-'} ~ ${end || '-'}`
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -309,32 +370,176 @@ export default {
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.erp-supplier-page {
|
||||
background: #eef1f3;
|
||||
padding: 16px;
|
||||
min-height: 100%;
|
||||
}
|
||||
.panel-card {
|
||||
border: 1px solid #d0d5d8;
|
||||
.surface-panel {
|
||||
background: #fff;
|
||||
border: 1px solid #d6dce1;
|
||||
border-radius: 4px;
|
||||
padding: 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
.panel-header {
|
||||
.surface-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-weight: 600;
|
||||
color: #1b2a38;
|
||||
}
|
||||
.inline-filter {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
.filter-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
> *:not(.filter-actions) {
|
||||
flex: 1 1 150px;
|
||||
}
|
||||
}
|
||||
.supplier-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
|
||||
gap: 12px;
|
||||
}
|
||||
.supplier-card {
|
||||
border: 1px solid #d6dce1;
|
||||
padding: 12px;
|
||||
border-radius: 4px;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
.card-head {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-weight: 600;
|
||||
color: #1f2d3d;
|
||||
align-items: flex-start;
|
||||
.title {
|
||||
font-weight: 600;
|
||||
margin: 0;
|
||||
color: #15212d;
|
||||
}
|
||||
.sub {
|
||||
margin: 2px 0 0;
|
||||
color: #79828c;
|
||||
font-size: 12px;
|
||||
}
|
||||
.tag-group {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
.toolbar {
|
||||
.card-body {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
li {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 13px;
|
||||
color: #4a5663;
|
||||
& + li {
|
||||
margin-top: 4px;
|
||||
}
|
||||
span {
|
||||
color: #8a96a3;
|
||||
}
|
||||
strong {
|
||||
color: #151e26;
|
||||
}
|
||||
}
|
||||
}
|
||||
.card-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
justify-content: flex-end;
|
||||
gap: 8px;
|
||||
.danger {
|
||||
color: #c0392b;
|
||||
}
|
||||
}
|
||||
.toolbar-input {
|
||||
width: 150px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
.cell-sub {
|
||||
font-size: 12px;
|
||||
color: #7c8792;
|
||||
.price-drawer {
|
||||
.price-drawer-body {
|
||||
padding: 16px 20px 12px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.drawer-header {
|
||||
margin-bottom: 12px;
|
||||
padding: 8px 10px;
|
||||
border-radius: 4px;
|
||||
background-color: #f5f7fa;
|
||||
border: 1px solid #e4e7ed;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
}
|
||||
.drawer-title-block {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.drawer-title {
|
||||
margin: 0;
|
||||
font-weight: 600;
|
||||
color: #1f2a37;
|
||||
}
|
||||
.drawer-sub {
|
||||
margin-top: 4px;
|
||||
color: #7a8694;
|
||||
font-size: 12px;
|
||||
}
|
||||
.drawer-section {
|
||||
margin-top: 14px;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
}
|
||||
.drawer-section-title {
|
||||
font-size: 13px;
|
||||
color: #5c6c7b;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
::v-deep .el-collapse-item__header {
|
||||
padding-left: 10px;
|
||||
}
|
||||
::v-deep .el-collapse-item__content {
|
||||
padding: 10px 10px 12px;
|
||||
}
|
||||
.price-info {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0 0 4px;
|
||||
li {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 13px;
|
||||
color: #4a5663;
|
||||
& + li {
|
||||
margin-top: 4px;
|
||||
}
|
||||
span {
|
||||
color: #8a96a3;
|
||||
}
|
||||
}
|
||||
}
|
||||
.price-actions {
|
||||
margin-top: 8px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 8px;
|
||||
.danger {
|
||||
color: #c0392b;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user