提交基础采购

This commit is contained in:
2025-11-18 16:45:05 +08:00
parent cc9b1c0e92
commit 7c04e13198
77 changed files with 5733 additions and 0 deletions

View File

@@ -0,0 +1,340 @@
<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>
</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>
</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>
<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-dialog :title="supplierDialog.title" :visible.sync="supplierDialog.visible" width="520px">
<el-form :model="supplierDialog.form" :rules="supplierRules" ref="supplierForm" label-width="90px" size="small">
<el-form-item label="编码" prop="supplierCode">
<el-input v-model="supplierDialog.form.supplierCode" />
</el-form-item>
<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>
<el-form-item label="信用等级">
<el-select v-model="supplierDialog.form.creditRating" 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>
</el-form-item>
<el-form-item label="联系人">
<el-input v-model="supplierDialog.form.contactPerson" />
</el-form-item>
<el-form-item label="联系电话">
<el-input v-model="supplierDialog.form.contactPhone" />
</el-form-item>
<el-form-item label="地址">
<el-input v-model="supplierDialog.form.address" />
</el-form-item>
<el-form-item label="备注">
<el-input type="textarea" v-model="supplierDialog.form.remark" />
</el-form-item>
</el-form>
<div slot="footer">
<el-button @click="supplierDialog.visible = false"> </el-button>
<el-button type="primary" @click="submitSupplier"> </el-button>
</div>
</el-dialog>
<!-- 价格弹窗 -->
<el-dialog :title="priceDialog.title" :visible.sync="priceDialog.visible" width="520px">
<el-form :model="priceDialog.form" :rules="priceRules" ref="priceForm" label-width="100px" size="small">
<el-form-item label="供应商" prop="supplierId">
<el-select v-model="priceDialog.form.supplierId" placeholder="选择供应商">
<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>
<el-form-item label="规格">
<el-input v-model="priceDialog.form.specification" />
</el-form-item>
<el-form-item label="含税价格" prop="price">
<el-input-number v-model="priceDialog.form.price" :min="0" :precision="2" />
</el-form-item>
<el-form-item label="有效期">
<el-date-picker
v-model="priceValidRange"
type="daterange"
value-format="yyyy-MM-dd"
start-placeholder="开始"
end-placeholder="结束"
/>
</el-form-item>
<el-form-item label="备注">
<el-input type="textarea" v-model="priceDialog.form.remark" />
</el-form-item>
</el-form>
<div slot="footer">
<el-button @click="priceDialog.visible = false"> </el-button>
<el-button type="primary" @click="submitPrice"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import {
listSupplier,
addSupplier,
updateSupplier,
delSupplier,
listSupplierPrice,
addSupplierPrice,
updateSupplierPrice,
delSupplierPrice
} from '@/api/erp/purchase'
export default {
name: 'ErpSupplierManage',
data() {
return {
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' }]
},
priceQuery: { pageNum: 1, pageSize: 50, supplierId: null, materialTypeCode: null },
priceList: [],
priceLoading: false,
priceDialog: { visible: false, title: '', form: {} },
priceRules: {
supplierId: [{ required: true, message: '请选择供应商', trigger: 'change' }],
materialTypeCode: [{ required: true, message: '请输入物料类型', trigger: 'blur' }],
price: [{ required: true, message: '请输入价格', trigger: 'change' }]
},
priceRange: [],
priceValidRange: [],
supplierOptions: []
}
},
created() {
this.loadSuppliers()
this.loadPrices()
},
methods: {
loadSuppliers() {
this.supplierLoading = true
listSupplier(this.supplierQuery)
.then(res => {
this.supplierList = res.rows || []
this.supplierOptions = this.supplierList
})
.finally(() => {
this.supplierLoading = false
})
},
resetSupplierQuery() {
this.supplierQuery = { pageNum: 1, pageSize: 50, name: null, creditRating: null }
this.loadSuppliers()
},
openSupplierDialog(row) {
if (row) {
this.supplierDialog.form = { ...row }
this.supplierDialog.title = '编辑供应商'
} else {
this.supplierDialog.form = { supplierCode: '', name: '', creditRating: 'A' }
this.supplierDialog.title = '新增供应商'
}
this.supplierDialog.visible = true
this.$nextTick(() => this.$refs.supplierForm && this.$refs.supplierForm.clearValidate())
},
submitSupplier() {
this.$refs.supplierForm.validate(valid => {
if (!valid) return
const api = this.supplierDialog.form.supplierId ? updateSupplier : addSupplier
api(this.supplierDialog.form).then(() => {
this.$message.success('保存成功')
this.supplierDialog.visible = false
this.loadSuppliers()
})
})
},
handleDeleteSupplier(row) {
this.$confirm('确认删除该供应商吗?', '提示').then(() => {
return delSupplier(row.supplierId)
}).then(() => {
this.$message.success('删除成功')
this.loadSuppliers()
})
},
// price
loadPrices() {
const query = { ...this.priceQuery }
if (this.priceRange && this.priceRange.length === 2) {
query.beginTime = this.priceRange[0]
query.endTime = this.priceRange[1]
}
this.priceLoading = true
listSupplierPrice(query)
.then(res => {
this.priceList = res.rows || []
})
.finally(() => {
this.priceLoading = false
})
},
matchSupplier(id) {
const target = this.supplierOptions.find(sp => sp.supplierId === id)
return target ? target.name : id
},
openPriceDialog(row) {
if (!this.supplierOptions.length) {
this.$message.warning('请先维护供应商')
return
}
if (row) {
this.priceDialog.form = { ...row }
this.priceValidRange = [row.validFrom, row.validTo]
this.priceDialog.title = '编辑价格'
} else {
this.priceDialog.form = { supplierId: null, materialTypeCode: '', price: 0 }
this.priceValidRange = []
this.priceDialog.title = '新增价格'
}
this.priceDialog.visible = true
this.$nextTick(() => this.$refs.priceForm && this.$refs.priceForm.clearValidate())
},
submitPrice() {
this.$refs.priceForm.validate(valid => {
if (!valid) return
if (this.priceValidRange && this.priceValidRange.length === 2) {
this.priceDialog.form.validFrom = this.priceValidRange[0]
this.priceDialog.form.validTo = this.priceValidRange[1]
}
const api = this.priceDialog.form.priceId ? updateSupplierPrice : addSupplierPrice
api(this.priceDialog.form).then(() => {
this.$message.success('保存成功')
this.priceDialog.visible = false
this.loadPrices()
})
})
},
handleDeletePrice(row) {
this.$confirm('确认删除该价格吗?', '提示').then(() => {
return delSupplierPrice(row.priceId)
}).then(() => {
this.$message.success('删除成功')
this.loadPrices()
})
}
}
}
</script>
<style lang="scss" scoped>
.erp-supplier-page {
background: #eef1f3;
padding: 16px;
min-height: 100%;
}
.panel-card {
border: 1px solid #d0d5d8;
}
.panel-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: 150px;
margin-right: 8px;
}
.cell-sub {
font-size: 12px;
color: #7c8792;
}
</style>