提交基础采购
This commit is contained in:
734
klp-ui/src/views/erp/purchase/index.vue
Normal file
734
klp-ui/src/views/erp/purchase/index.vue
Normal file
@@ -0,0 +1,734 @@
|
||||
<template>
|
||||
<div class="erp-purchase-page">
|
||||
<el-row :gutter="16" class="summary-row">
|
||||
<el-col :span="6">
|
||||
<div class="summary-card">
|
||||
<p class="label">采购总金额</p>
|
||||
<p class="value">¥{{ summary.totalAmount | formatAmount }}</p>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<div class="summary-card">
|
||||
<p class="label">计划采购量</p>
|
||||
<p class="value">{{ summary.suggestionTotal }} 吨</p>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<div class="summary-card">
|
||||
<p class="label">待处理订单</p>
|
||||
<p class="value">{{ summary.pendingOrder }}</p>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<div class="summary-card">
|
||||
<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>
|
||||
<el-table :data="mappingRows" border size="small" class="mapping-table">
|
||||
<el-table-column label="产品ID" width="160">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.productId" placeholder="产品ID" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="原料ID" width="160">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.rawMaterialId" placeholder="原料ID" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="转换率" width="140">
|
||||
<template slot-scope="scope">
|
||||
<el-input-number v-model="scope.row.conversionRate" :min="0" :max="1" :step="0.01" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="120">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" @click="removeMappingRow(scope.$index)" :disabled="mappingRows.length === 1">移除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="mapping-toolbar">
|
||||
<el-button icon="el-icon-plus" size="mini" @click="addMappingRow">新增映射</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
:data="analysisData"
|
||||
v-loading="analysisLoading"
|
||||
size="small"
|
||||
border
|
||||
class="analysis-table"
|
||||
show-summary
|
||||
:summary-method="analysisSummary"
|
||||
>
|
||||
<el-table-column label="产品" prop="productName" min-width="180">
|
||||
<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">
|
||||
<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>
|
||||
</el-card>
|
||||
|
||||
<el-card class="panel-card" shadow="never">
|
||||
<div slot="header" class="panel-header">
|
||||
<span>执行控制</span>
|
||||
</div>
|
||||
<el-tabs v-model="activeTab" type="border-card">
|
||||
<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>
|
||||
<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">
|
||||
<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 label="操作" width="160">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="mini" @click="openReceiptDialog(scope.row)">编辑</el-button>
|
||||
<el-button type="text" size="mini" @click="handleDeleteReceipt(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination
|
||||
v-show="receiptTotal > 0"
|
||||
:total="receiptTotal"
|
||||
:page.sync="receiptQuery.pageNum"
|
||||
:limit.sync="receiptQuery.pageSize"
|
||||
@pagination="loadReceipts"
|
||||
/>
|
||||
</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">
|
||||
<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>
|
||||
<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">
|
||||
<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="handleDeleteReturn(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination
|
||||
v-show="returnTotal > 0"
|
||||
:total="returnTotal"
|
||||
:page.sync="returnQuery.pageNum"
|
||||
:limit.sync="returnQuery.pageSize"
|
||||
@pagination="loadReturns"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-card>
|
||||
|
||||
<el-card class="panel-card" shadow="never">
|
||||
<div slot="header" class="panel-header">
|
||||
<span>采购报表</span>
|
||||
<div class="panel-actions">
|
||||
<el-date-picker
|
||||
v-model="reportRange"
|
||||
type="monthrange"
|
||||
unlink-panels
|
||||
value-format="yyyy-MM"
|
||||
range-separator="至"
|
||||
start-placeholder="开始月份"
|
||||
end-placeholder="结束月份"
|
||||
@change="loadReports"
|
||||
size="small"
|
||||
/>
|
||||
</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>
|
||||
|
||||
<!-- 收货弹窗 -->
|
||||
<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-form-item>
|
||||
<el-form-item label="明细ID" prop="itemId">
|
||||
<el-input v-model="receiptDialog.form.itemId" />
|
||||
</el-form-item>
|
||||
<el-form-item label="收货数量" prop="receivedQty">
|
||||
<el-input-number v-model="receiptDialog.form.receivedQty" :min="0" :precision="3" />
|
||||
</el-form-item>
|
||||
<el-form-item label="质检结果" prop="qualityResult">
|
||||
<el-select v-model="receiptDialog.form.qualityResult" clearable placeholder="默认合格">
|
||||
<el-option label="合格" value="OK" />
|
||||
<el-option label="不合格" value="NG" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="收货时间">
|
||||
<el-date-picker
|
||||
v-model="receiptDialog.form.receiptTime"
|
||||
type="datetime"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
placeholder="自动取当前"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input type="textarea" v-model="receiptDialog.form.remark" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer">
|
||||
<el-button @click="receiptDialog.visible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="submitReceipt">保 存</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 退货弹窗 -->
|
||||
<el-dialog :title="returnDialog.title" :visible.sync="returnDialog.visible" width="500px">
|
||||
<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-form-item>
|
||||
<el-form-item label="退货类型">
|
||||
<el-select v-model="returnDialog.form.returnType" clearable>
|
||||
<el-option label="质量问题" value="QUALITY" />
|
||||
<el-option label="数量错误" value="QTY" />
|
||||
<el-option label="规格不符" value="SPEC" />
|
||||
<el-option label="其他" value="OTHER" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="退货原因">
|
||||
<el-input type="textarea" v-model="returnDialog.form.reason" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-select v-model="returnDialog.form.status">
|
||||
<el-option label="草稿" :value="0" />
|
||||
<el-option label="完成" :value="1" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input type="textarea" v-model="returnDialog.form.remark" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer">
|
||||
<el-button @click="returnDialog.visible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="submitReturn">保 存</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 退货明细弹窗 -->
|
||||
<el-dialog :title="returnItemDialog.title" :visible.sync="returnItemDialog.visible" width="520px">
|
||||
<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 class="toolbar-spacer"></div>
|
||||
<el-button type="primary" size="small" @click="openReturnItemForm()">新增明细</el-button>
|
||||
</div>
|
||||
<el-table :data="returnItemList" v-loading="returnItemLoading" border size="small">
|
||||
<el-table-column prop="returnItemId" label="ID" width="80" />
|
||||
<el-table-column prop="returnId" label="退货单ID" width="100" />
|
||||
<el-table-column prop="itemId" label="订单明细ID" width="120" />
|
||||
<el-table-column prop="returnQty" label="退货数量" width="120" />
|
||||
<el-table-column label="操作" width="140">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="mini" @click="openReturnItemForm(scope.row)">编辑</el-button>
|
||||
<el-button type="text" size="mini" @click="handleDeleteReturnItem(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination
|
||||
v-show="returnItemTotal > 0"
|
||||
:total="returnItemTotal"
|
||||
:page.sync="returnItemQuery.pageNum"
|
||||
:limit.sync="returnItemQuery.pageSize"
|
||||
@pagination="loadReturnItems"
|
||||
/>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 退货明细编辑 -->
|
||||
<el-dialog :title="returnItemFormDialog.title" :visible.sync="returnItemFormDialog.visible" width="420px">
|
||||
<el-form ref="returnItemForm" :model="returnItemFormDialog.form" :rules="returnItemRules" label-width="110px" size="small">
|
||||
<el-form-item label="退货单ID" prop="returnId">
|
||||
<el-input v-model="returnItemFormDialog.form.returnId" />
|
||||
</el-form-item>
|
||||
<el-form-item label="订单明细ID" prop="itemId">
|
||||
<el-input v-model="returnItemFormDialog.form.itemId" />
|
||||
</el-form-item>
|
||||
<el-form-item label="退货数量" prop="returnQty">
|
||||
<el-input-number v-model="returnItemFormDialog.form.returnQty" :min="0" :precision="3" />
|
||||
</el-form-item>
|
||||
<el-form-item label="照片">
|
||||
<el-input v-model="returnItemFormDialog.form.photos" placeholder="图片URL,用逗号分隔" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input type="textarea" v-model="returnItemFormDialog.form.remark" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer">
|
||||
<el-button @click="returnItemFormDialog.visible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="submitReturnItem">保 存</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
analyzePurchaseRequirement,
|
||||
listPurchaseReceipt,
|
||||
addPurchaseReceipt,
|
||||
updatePurchaseReceipt,
|
||||
delPurchaseReceipt,
|
||||
listPurchaseReturn,
|
||||
addPurchaseReturn,
|
||||
updatePurchaseReturn,
|
||||
delPurchaseReturn,
|
||||
listPurchaseReturnItem,
|
||||
addPurchaseReturnItem,
|
||||
updatePurchaseReturnItem,
|
||||
delPurchaseReturnItem,
|
||||
getPurchaseReportSummary,
|
||||
getPurchasePriceTrend,
|
||||
getSupplierQuality
|
||||
} from '@/api/erp/purchase'
|
||||
|
||||
export default {
|
||||
name: 'ErpPurchaseWorkbench',
|
||||
data() {
|
||||
return {
|
||||
mappingRows: [{ productId: '', rawMaterialId: '', conversionRate: 1 }],
|
||||
persistResult: false,
|
||||
analysisLoading: false,
|
||||
analysisData: [],
|
||||
summary: { totalAmount: 0, suggestionTotal: 0, pendingOrder: 0, supplierBrief: [] },
|
||||
reportRange: [],
|
||||
priceTrend: [],
|
||||
supplierQuality: [],
|
||||
activeTab: 'receipt',
|
||||
receiptList: [],
|
||||
receiptTotal: 0,
|
||||
receiptLoading: false,
|
||||
receiptQuery: { pageNum: 1, pageSize: 10, orderId: null, itemId: null },
|
||||
receiptDialog: { visible: false, title: '', form: {} },
|
||||
receiptRules: {
|
||||
orderId: [{ required: true, message: '请输入订单ID', trigger: 'blur' }],
|
||||
itemId: [{ required: true, message: '请输入明细ID', trigger: 'blur' }],
|
||||
receivedQty: [{ required: true, message: '请输入收货数量', trigger: 'blur' }]
|
||||
},
|
||||
returnList: [],
|
||||
returnTotal: 0,
|
||||
returnLoading: false,
|
||||
returnQuery: { pageNum: 1, pageSize: 10, orderId: null, status: null },
|
||||
returnDialog: { visible: false, title: '', form: {} },
|
||||
returnRules: {
|
||||
orderId: [{ required: true, message: '请输入订单ID', trigger: 'blur' }]
|
||||
},
|
||||
returnItemDialog: { visible: false, title: '退货明细列表' },
|
||||
returnItemQuery: { pageNum: 1, pageSize: 10, returnId: null, itemId: null },
|
||||
returnItemList: [],
|
||||
returnItemTotal: 0,
|
||||
returnItemLoading: false,
|
||||
returnItemFormDialog: { visible: false, title: '', form: {} },
|
||||
returnItemRules: {
|
||||
returnId: [{ required: true, message: '请输入退货单ID', trigger: 'blur' }],
|
||||
itemId: [{ required: true, message: '请输入订单明细ID', trigger: 'blur' }],
|
||||
returnQty: [{ required: true, message: '请输入退货数量', trigger: 'blur' }]
|
||||
}
|
||||
}
|
||||
},
|
||||
filters: {
|
||||
formatAmount(val) {
|
||||
if (!val) return '0.00'
|
||||
return Number(val).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadReports()
|
||||
this.loadReceipts()
|
||||
this.loadReturns()
|
||||
},
|
||||
methods: {
|
||||
addMappingRow() {
|
||||
this.mappingRows.push({ productId: '', rawMaterialId: '', conversionRate: 1 })
|
||||
},
|
||||
removeMappingRow(index) {
|
||||
if (this.mappingRows.length === 1) return
|
||||
this.mappingRows.splice(index, 1)
|
||||
},
|
||||
handleAnalyze() {
|
||||
if (!this.mappingRows.every(row => row.productId && row.rawMaterialId)) {
|
||||
this.$message.warning('请补全产品与原料映射')
|
||||
return
|
||||
}
|
||||
this.analysisLoading = true
|
||||
const payload = {
|
||||
mappings: this.mappingRows.map(row => ({
|
||||
productId: Number(row.productId),
|
||||
rawMaterialId: Number(row.rawMaterialId),
|
||||
conversionRate: Number(row.conversionRate || 0)
|
||||
})),
|
||||
persistResult: this.persistResult
|
||||
}
|
||||
analyzePurchaseRequirement(payload)
|
||||
.then(res => {
|
||||
this.analysisData = res || []
|
||||
this.summary.suggestionTotal = this.analysisData.reduce((sum, item) => sum + Number(item.suggestedPurchase || 0), 0)
|
||||
this.$message.success('分析完成')
|
||||
})
|
||||
.finally(() => {
|
||||
this.analysisLoading = false
|
||||
})
|
||||
},
|
||||
analysisSummary({ data }) {
|
||||
const sums = []
|
||||
const columns = ['salesDemand', 'productStockWeight', 'rawStockConverted', 'inTransitConverted', 'pendingConverted', 'suggestedPurchase']
|
||||
sums[0] = '总计'
|
||||
data.forEach(row => {
|
||||
columns.forEach((col, idx) => {
|
||||
const value = Number(row[col] || 0)
|
||||
sums[idx + 2] = (Number(sums[idx + 2]) || 0) + value
|
||||
})
|
||||
})
|
||||
return sums
|
||||
},
|
||||
loadReports() {
|
||||
const params = {}
|
||||
if (this.reportRange && this.reportRange.length === 2) {
|
||||
params.beginTime = `${this.reportRange[0]}-01`
|
||||
params.endTime = `${this.reportRange[1]}-31`
|
||||
}
|
||||
getPurchaseReportSummary(params).then(res => {
|
||||
this.summary.totalAmount = res.totalAmount || 0
|
||||
this.summary.supplierBrief = res.bySupplier || []
|
||||
this.summary.pendingOrder = this.summary.supplierBrief.reduce((sum, item) => sum + (item.orderCount || 0), 0)
|
||||
})
|
||||
getPurchasePriceTrend(params).then(res => {
|
||||
this.priceTrend = res || []
|
||||
})
|
||||
getSupplierQuality(params).then(res => {
|
||||
this.supplierQuality = res || []
|
||||
})
|
||||
},
|
||||
formatPercent(value) {
|
||||
if (!value || !isFinite(value)) return '0%'
|
||||
return `${(Number(value) * 100).toFixed(2)}%`
|
||||
},
|
||||
// 收货
|
||||
loadReceipts() {
|
||||
this.receiptLoading = true
|
||||
listPurchaseReceipt(this.receiptQuery)
|
||||
.then(res => {
|
||||
this.receiptList = res.rows || []
|
||||
this.receiptTotal = res.total || 0
|
||||
})
|
||||
.finally(() => {
|
||||
this.receiptLoading = false
|
||||
})
|
||||
},
|
||||
resetReceiptQuery() {
|
||||
this.receiptQuery = { pageNum: 1, pageSize: 10, orderId: null, itemId: null }
|
||||
this.loadReceipts()
|
||||
},
|
||||
openReceiptDialog(row) {
|
||||
if (row) {
|
||||
this.receiptDialog.form = { ...row }
|
||||
this.receiptDialog.title = '编辑收货'
|
||||
} else {
|
||||
this.receiptDialog.form = { orderId: '', itemId: '', receivedQty: 0, qualityResult: 'OK' }
|
||||
this.receiptDialog.title = '新增收货'
|
||||
}
|
||||
this.receiptDialog.visible = true
|
||||
this.$nextTick(() => this.$refs.receiptForm && this.$refs.receiptForm.clearValidate())
|
||||
},
|
||||
submitReceipt() {
|
||||
this.$refs.receiptForm.validate(valid => {
|
||||
if (!valid) return
|
||||
const api = this.receiptDialog.form.receiptId ? updatePurchaseReceipt : addPurchaseReceipt
|
||||
api(this.receiptDialog.form).then(() => {
|
||||
this.$message.success('保存成功')
|
||||
this.receiptDialog.visible = false
|
||||
this.loadReceipts()
|
||||
})
|
||||
})
|
||||
},
|
||||
handleDeleteReceipt(row) {
|
||||
this.$confirm('确定删除该收货记录吗?', '提示').then(() => {
|
||||
return delPurchaseReceipt(row.receiptId)
|
||||
}).then(() => {
|
||||
this.$message.success('删除成功')
|
||||
this.loadReceipts()
|
||||
})
|
||||
},
|
||||
// 退货
|
||||
loadReturns() {
|
||||
this.returnLoading = true
|
||||
listPurchaseReturn(this.returnQuery)
|
||||
.then(res => {
|
||||
this.returnList = res.rows || []
|
||||
this.returnTotal = res.total || 0
|
||||
})
|
||||
.finally(() => {
|
||||
this.returnLoading = false
|
||||
})
|
||||
},
|
||||
resetReturnQuery() {
|
||||
this.returnQuery = { pageNum: 1, pageSize: 10, orderId: null, status: null }
|
||||
this.loadReturns()
|
||||
},
|
||||
openReturnDialog(row) {
|
||||
if (row) {
|
||||
this.returnDialog.form = { ...row }
|
||||
this.returnDialog.title = '编辑退货单'
|
||||
} else {
|
||||
this.returnDialog.form = { orderId: '', returnType: 'QUALITY', status: 0 }
|
||||
this.returnDialog.title = '新增退货单'
|
||||
}
|
||||
this.returnDialog.visible = true
|
||||
this.$nextTick(() => this.$refs.returnForm && this.$refs.returnForm.clearValidate())
|
||||
},
|
||||
submitReturn() {
|
||||
this.$refs.returnForm.validate(valid => {
|
||||
if (!valid) return
|
||||
const api = this.returnDialog.form.returnId ? updatePurchaseReturn : addPurchaseReturn
|
||||
api(this.returnDialog.form).then(() => {
|
||||
this.$message.success('保存成功')
|
||||
this.returnDialog.visible = false
|
||||
this.loadReturns()
|
||||
})
|
||||
})
|
||||
},
|
||||
handleDeleteReturn(row) {
|
||||
this.$confirm('确定删除该退货单吗?', '提示').then(() => {
|
||||
return delPurchaseReturn(row.returnId)
|
||||
}).then(() => {
|
||||
this.$message.success('删除成功')
|
||||
this.loadReturns()
|
||||
})
|
||||
},
|
||||
// 退货明细
|
||||
openReturnItemDialog() {
|
||||
this.returnItemDialog.visible = true
|
||||
this.loadReturnItems()
|
||||
},
|
||||
loadReturnItems() {
|
||||
this.returnItemLoading = true
|
||||
listPurchaseReturnItem(this.returnItemQuery)
|
||||
.then(res => {
|
||||
this.returnItemList = res.rows || []
|
||||
this.returnItemTotal = res.total || 0
|
||||
})
|
||||
.finally(() => {
|
||||
this.returnItemLoading = false
|
||||
})
|
||||
},
|
||||
resetReturnItemQuery() {
|
||||
this.returnItemQuery = { pageNum: 1, pageSize: 10, returnId: null, itemId: null }
|
||||
this.loadReturnItems()
|
||||
},
|
||||
openReturnItemForm(row) {
|
||||
if (row) {
|
||||
this.returnItemFormDialog.form = { ...row }
|
||||
this.returnItemFormDialog.title = '编辑退货明细'
|
||||
} else {
|
||||
this.returnItemFormDialog.form = { returnId: '', itemId: '', returnQty: 0 }
|
||||
this.returnItemFormDialog.title = '新增退货明细'
|
||||
}
|
||||
this.returnItemFormDialog.visible = true
|
||||
this.$nextTick(() => this.$refs.returnItemForm && this.$refs.returnItemForm.clearValidate())
|
||||
},
|
||||
submitReturnItem() {
|
||||
this.$refs.returnItemForm.validate(valid => {
|
||||
if (!valid) return
|
||||
const api = this.returnItemFormDialog.form.returnItemId ? updatePurchaseReturnItem : addPurchaseReturnItem
|
||||
api(this.returnItemFormDialog.form).then(() => {
|
||||
this.$message.success('保存成功')
|
||||
this.returnItemFormDialog.visible = false
|
||||
this.loadReturnItems()
|
||||
})
|
||||
})
|
||||
},
|
||||
handleDeleteReturnItem(row) {
|
||||
this.$confirm('确定删除该退货明细吗?', '提示').then(() => {
|
||||
return delPurchaseReturnItem(row.returnItemId)
|
||||
}).then(() => {
|
||||
this.$message.success('删除成功')
|
||||
this.loadReturnItems()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<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;
|
||||
}
|
||||
}
|
||||
.panel-card {
|
||||
margin-bottom: 18px;
|
||||
border: 1px solid #d0d5d8;
|
||||
background: #fff;
|
||||
}
|
||||
.panel-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-weight: 600;
|
||||
color: #1f2d3d;
|
||||
}
|
||||
.panel-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
.mapping-table {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.mapping-toolbar {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.analysis-table {
|
||||
margin-top: 8px;
|
||||
}
|
||||
.cell-title {
|
||||
font-weight: 600;
|
||||
color: #1f2d3d;
|
||||
}
|
||||
.cell-sub {
|
||||
color: #7c8792;
|
||||
font-size: 12px;
|
||||
}
|
||||
.toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
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;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user