采购计划商品选择和编辑

This commit is contained in:
weiwei committed 2025-02-15 11:35:07 +08:00
1 parent 14ec12cfca
commit a5958a451a
4 files changed
+356 -151

No files matched your search

+2
View File
@@ -19,6 +19,7 @@
"@element-plus/icons-vue": "^2.0.10",
"@popperjs/core": "2.11.8",
"@vueuse/core": "^10.4.1",
"@vxe-ui/plugin-render-element": "^4.0.10",
"@wangeditor/editor": "5.1.23",
"@wangeditor/editor-for-vue": "5.1.12",
"autoprefixer": "^10.4.7",
@@ -56,6 +57,7 @@
"vue3-tree-org": "^4.2.2",
"vue3-video-play": "1.3.1-beta.6",
"vuedraggable": "^4.1.0",
"vxe-pc-ui": "^4.3.85",
"vxe-table": "^4.10.15"
},
"devDependencies": {
+40 -24
View File
@@ -1,41 +1,57 @@
import request from "/@/utils/request"
export function fetchList(query?: Object) {
return request({
url: '/supermarket/smErpCgPlan/page',
method: 'get',
params: query
})
return request({
url: "/supermarket/smErpCgPlan/page",
method: "get",
params: query,
})
}
export function addObj(obj?: Object) {
return request({
url: '/supermarket/smErpCgPlan',
method: 'post',
data: obj
})
return request({
url: "/supermarket/smErpCgPlan",
method: "post",
data: obj,
})
}
export function getObj(id?: string) {
return request({
url: '/supermarket/smErpCgPlan/' + id,
method: 'get'
})
return request({
url: "/supermarket/smErpCgPlan/" + id,
method: "get",
})
}
export function delObjs(ids?: Object) {
return request({
url: '/supermarket/smErpCgPlan',
method: 'delete',
data: ids
})
return request({
url: "/supermarket/smErpCgPlan",
method: "delete",
data: ids,
})
}
export function putObj(obj?: Object) {
return request({
url: '/supermarket/smErpCgPlan',
method: 'put',
data: obj
})
return request({
url: "/supermarket/smErpCgPlan",
method: "put",
data: obj,
})
}
// 获取采购计划编号
export function getPlanCode() {
return request({
url: "/supermarket/sm/common/getSequence",
method: "get",
params: { type: 1 },
})
}
// 获取采购计划选择商品的列表
export function getCgPlanSpuPage() {
return request({
url: "/supermarket/smErpCgPlan/erpSpuPage",
method: "get",
})
}
+6
View File
@@ -8,8 +8,11 @@ import { i18n } from "/@/i18n"
import { properties } from "/@/utils/globalProperties"
import { initAntiDebug } from "/@/utils/anti-debug"
import "/@/assets/styles/global.scss"
import VxeUI from "vxe-pc-ui"
import VxeUITable from "vxe-table"
import "vxe-table/lib/style.css"
import VxeUIPluginRenderElement from "@vxe-ui/plugin-render-element"
import "@vxe-ui/plugin-render-element/dist/style.css"
// Initialize anti-debug protection
initAntiDebug()
@@ -25,10 +28,13 @@ properties(app)
// 全局自定义指令挂载
directive(app)
VxeUI.use(VxeUIPluginRenderElement)
app
.use(pinia) // pinia 存储
.use(router) // 路由
.use(Components) // 全局引入自定义的组件&第三方的组件
.use(i18n) // 国际化
.use(VxeUI)
.use(VxeUITable)
.mount("#app")
@@ -2,35 +2,44 @@
<div class="layout-padding">
<div class="layout-padding-auto layout-padding-view" style="overflow: scroll">
<el-form ref="dataFormRef" :model="form" :rules="dataRules" formDialogRef label-width="140px" v-loading="loading">
<el-row>
<div class="flex flex-wrap">
<el-form-item label="采购计划编号" prop="planCode">
<el-input v-model="form.planCode" placeholder="请输入采购计划编号" />
</el-form-item>
<el-form-item label="采购计划单据日期" prop="planDate">
<el-input v-model="form.planDate" placeholder="请输入采购计划单据日期" />
</el-form-item>
<!-- <el-form-item label="仓库" prop="warehouseId">-->
<!-- <el-input v-model="form.warehouseId" placeholder="请输入仓库id" />-->
<!-- </el-form-item>-->
<el-form-item label="经办人" prop="handlerUserId">
<el-input v-model="form.handlerUserId" placeholder="请输入经办人id" />
</el-form-item>
<el-form-item label="货商" prop="supplierId">
<el-input v-model="form.supplierId" placeholder="请输入货商" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" placeholder="请输入备注" />
<el-input v-model="form.planCode" placeholder="请输入采购计划编号" disabled style="width: 200px" />
</el-form-item>
<el-form-item label="订单编号" prop="orderNumber">
<el-input v-model="form.orderNumber" placeholder="请输入订单编号" />
<el-input v-model="form.orderNumber" placeholder="请输入订单编号" style="width: 200px" />
</el-form-item>
</el-row>
<el-form-item label="采购计划单据日期" prop="planDate">
<el-date-picker
style="width: 200px"
v-model="form.planDate"
type="date"
placeholder="请选择采购计划单据日期"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
/>
</el-form-item>
<el-form-item label="货商" prop="supplierId">
<el-select v-model="form.supplierId" placeholder="请选择货商" style="width: 200px">
<el-option v-for="item in supplierDict" :key="item?.id" :label="item?.typeName" :value="item?.id" />
</el-select>
</el-form-item>
<!-- <el-form-item label="仓库" prop="warehouseId">
<el-input v-model="form.warehouseId" placeholder="请输入仓库id" />
</el-form-item> -->
<el-form-item label="经办人" prop="handlerUserId">
<el-input v-model="form.handlerUserId" placeholder="请输入经办人" style="width: 200px" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" placeholder="请输入备注" style="width: 200px" />
</el-form-item>
</div>
</el-form>
<el-row class="my-3">
@@ -50,7 +59,10 @@
/>
行新增
</el-button>
<el-button @click="removeSelectRowEvent" :disabled="state.selectedRowsIds.length <= 0">删除选中</el-button>
<el-button @click="removeSelectRowEvent" :disabled="state.selectedRowsErpSpuIds.length <= 0">
删除选中
</el-button>
<el-button @click="handleClickSpuSelect">商品选择</el-button>
</el-row>
<vxe-table
@@ -64,7 +76,7 @@
mode: 'cell',
beforeEditMethod({ row, column }:any) {
// name 为 'x' 开头的列禁止编辑
if (column.property === 'quantity') {
if (column.property === '') {
return false
}
return true
@@ -78,56 +90,51 @@
@checkbox-all="selectChangeEvent"
@checkbox-change="selectChangeEvent"
size="mini"
empty-text="无数据"
align="center"
>
<vxe-column type="checkbox" width="40" fixed="left"></vxe-column>
<vxe-column type="seq" width="50" fixed="left"></vxe-column>
<!-- <vxe-column field="planId" title="采购" :edit-render="{ autoFocus: 'input', placeholder: '请输入' }">-->
<!-- <template #edit="{ row }">-->
<!-- <el-input v-model="row.planId" />-->
<!-- </template>-->
<!-- </vxe-column>-->
<!-- <vxe-column field="planId" title="采购" :edit-render="{ autoFocus: 'input', placeholder: '请输入' }">-->
<!-- <template #edit="{ row }">-->
<!-- <el-input v-model="row.planId" />-->
<!-- </template>-->
<!-- </vxe-column>-->
<vxe-column field="erpSpuId" title="库存商品" :edit-render="{ autoFocus: 'input', placeholder: '请输入' }">
<vxe-column field="productName" title="库存商品" />
<vxe-column field="unitId" title="包装单位" :edit-render="{}">
<template #edit="{ row }">
<el-input v-model="row.erpSpuId" />
<el-select v-model="row.unitId" placeholder="请选择包装单位">
<el-option v-for="item in row.erpUnitVos" :key="item.id" :label="item.unit" :value="item.id" />
</el-select>
</template>
<template #default="{ row }">
<span v-if="row.unitId">{{ row.erpUnitVos.find((item: any) => item.id == row.unitId)?.unit }}</span>
<span v-else style="color: #c0c4cf">请选择</span>
</template>
</vxe-column>
<!-- <vxe-column field="merchantId" title="商户编号" :edit-render="{ autoFocus: 'input', placeholder: '请选择' }">-->
<!-- <template #edit="{ row }">-->
<!-- <select-mch v-model="row.merchantId" />-->
<!-- </template>-->
<!-- </vxe-column>-->
<!-- <vxe-column field="deptId" title="部门id" :edit-render="{ autoFocus: 'input', placeholder: '请输入' }">-->
<!-- <template #edit="{ row }">-->
<!-- <el-input v-model="row.deptId" />-->
<!-- </template>-->
<!-- </vxe-column>-->
<vxe-column field="unitId" title="包装单位" :edit-render="{ autoFocus: 'input', placeholder: '请输入' }">
<template #edit="{ row }">
<el-input v-model="row.unitId" />
</template>
</vxe-column>
<vxe-column field="quantity" title="数量" :edit-render="{ autoFocus: 'input', placeholder: '请输入' }">
<template #edit="{ row }">
<el-input v-model="row.quantity" />
</template>
</vxe-column>
<vxe-column field="unitPrice" title="进价" :edit-render="{ autoFocus: 'input', placeholder: '请输入' }">
<template #edit="{ row }">
<el-input v-model="row.unitPrice" />
<vxe-column field="unitPrice" title="进价">
<template #default="{ row }">
{{ row.erpUnitVos.find((item: any) => item.id == row.unitId)?.purchasePrice }}
</template>
</vxe-column>
<vxe-column field="totalAmount" title="累计总金额" :edit-render="{ autoFocus: 'input', placeholder: '请输入' }">
<template #edit="{ row }">
<el-input v-model="row.totalAmount" />
<vxe-column field="totalAmount" title="累计总金额">
<template #default="{ row }">
{{
row.unitId && row.quantity
? Number(row.erpUnitVos.find((item: any) => item.id == row.unitId)?.purchasePrice) * row.quantity
: ""
}}
</template>
</vxe-column>
@@ -137,6 +144,17 @@
</template>
</vxe-column>
<!-- <vxe-column field="merchantId" title="商户编号" :edit-render="{ autoFocus: 'input', placeholder: '请选择' }">-->
<!-- <template #edit="{ row }">-->
<!-- <select-mch v-model="row.merchantId" />-->
<!-- </template>-->
<!-- </vxe-column>-->
<!-- <vxe-column field="deptId" title="部门id" :edit-render="{ autoFocus: 'input', placeholder: '请输入' }">-->
<!-- <template #edit="{ row }">-->
<!-- <el-input v-model="row.deptId" />-->
<!-- </template>-->
<!-- </vxe-column>-->
</vxe-table>
<el-row class="my-3">
@@ -144,6 +162,75 @@
<el-button type="primary" plain @click="onSubmit">继续添加</el-button>
<el-button type="primary" plain @click="onSubmit">保存</el-button>
</el-row>
<!-- 商品选择对话框 -->
<el-dialog
v-model="state.spuSelectDialogVisible"
title="选择商品"
width="60%"
:close-on-click-modal="false"
draggable
@close="state.selectedSpuObjs = []"
>
<!-- <el-row>
<el-form :model="foodQueryForm" ref="queryRef" :inline="true" @keyup.enter="getDataListAndSelect">
<el-form-item label="商品名称" prop="name">
<el-input placeholder="请输入商品名称" v-model="foodQueryForm.name" />
</el-form-item>
<el-form-item label="商品分类" prop="categoryId">
<select-ctcg v-model="foodQueryForm.categoryId" style="width: 200px" />
</el-form-item>
<el-form-item>
<el-button icon="search" type="primary" @click="getDataListAndSelect">查询</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</el-row> -->
<el-table
ref="spuMultipleTableRef"
:data="state.spuDataList"
v-loading="spuListLoading"
@select="handleSelect"
@select-all="handleSelectAll"
@selection-change="selectionChangeHandle"
:row-key="(row:any) => row.id"
:reserve-selection="true"
@row-click="rowClick"
:row-style="{ cursor: 'pointer' }"
>
<el-table-column type="selection" width="40" align="center" fixed="left" />
<el-table-column type="index" label="#" width="50" align="center" fixed="left" />
<el-table-column prop="productName" label="商品名称" min-width="100px" align="center" show-overflow-tooltip />
<el-table-column prop="barcode" label="自编码/条码" min-width="100px" align="center" show-overflow-tooltip />
<el-table-column prop="productCode" label="货号" min-width="100px" align="center" show-overflow-tooltip />
<el-table-column prop="brandId" label="品牌" min-width="100px" align="center" show-overflow-tooltip />
<el-table-column prop="categoryId" label="分类" min-width="100px" align="center" show-overflow-tooltip />
<el-table-column prop="deptId" label="商户" min-width="100px" align="center" show-overflow-tooltip />
<el-table-column prop="supplierId" label="货商" min-width="100px" align="center" show-overflow-tooltip />
<el-table-column prop="status" label="状态" min-width="100px" align="center" show-overflow-tooltip />
<el-table-column prop="picUrl" label="商品封面图" align="center" show-overflow-tooltip>
<template #default="scope">
<preview-image @click.stop :src="scope.row.picUrl" />
</template>
</el-table-column>
<el-table-column prop="stock" label="库存" min-width="100px" align="center" show-overflow-tooltip />
</el-table>
<!-- <pagination
@size-change="sizeChangeHandle"
@current-change="currentChangeHandle"
v-model:current-page="foodQueryForm.current"
v-model:page-size="foodQueryForm.size"
:total="total"
/> -->
<template #footer>
<div class="dialog-footer">
<el-button @click="state.spuSelectDialogVisible = false">取消</el-button>
<el-button type="primary" @click="handleSelectDialogConfirm" :disabled="loading">确认</el-button>
</div>
</template>
</el-dialog>
</div>
</div>
</template>
@@ -151,15 +238,13 @@
<script setup lang="ts" name="SmErpCgPlanDialog">
import { useDict } from "/@/hooks/dict"
import { useMessage } from "/@/hooks/message"
import { getObj, addObj, putObj } from "/@/api/supermarketerp/smErpCgPlan"
import { getObj, addObj, putObj, getPlanCode, getCgPlanSpuPage } from "/@/api/supermarketerp/smErpCgPlan"
import { VxeTableEvents, VxeTablePropTypes, VxeUI, type VxeTableInstance } from "vxe-table"
import { getSupplierTypeOptions } from "/@/api/supermarketerp/smErpSupplier"
interface RowVO {
id: string
planId: string
id?: string
erpSpuId: string
merchantId: string
deptId: string
quantity: number | null
unitPrice: number | null
totalAmount: number | null
@@ -169,95 +254,89 @@ interface RowVO {
// 定义变量内容
const loading = ref(false)
const spuListLoading = ref(false)
const dataFormRef = ref()
const tableRef = ref<VxeTableInstance<RowVO>>()
const spuMultipleTableRef = ref()
const supplierDict = ref<any[]>([]) // 货商下拉选项
// 提交表单数据
const form = reactive({
id: "",
planCode: "",
planDate: "",
warehouseId: "",
handlerUserId: "",
checkStatus: "",
checkUserId: "",
checkTime: "",
merchantId: "",
deptId: "",
quantity: "",
totalNumber: "",
totalAmount: "",
supplierId: "",
remark: "",
orderNumber: "",
planDate: "",
supplierId: "",
handlerUserId: "",
remark: "",
})
const state = reactive<{
tableData: RowVO[]
insertRecords: RowVO[]
selectedRowsIds: string[]
selectedRowsErpSpuIds: string[]
insertRowNumber: number
spuSelectDialogVisible: boolean
spuDataList: any[]
selectedSpuObjs: any[]
}>({
tableData: [
{
id: "11",
planId: "11",
erpSpuId: "11",
merchantId: "11",
deptId: "11",
quantity: 11,
unitPrice: 11,
totalAmount: 11,
remark: "11",
unitId: "11",
},
{
id: "22",
planId: "22",
erpSpuId: "22",
merchantId: "22",
deptId: "22",
quantity: 11,
unitPrice: 11,
totalAmount: 11,
remark: "22",
unitId: "22",
},
],
insertRecords: [],
selectedRowsIds: [],
tableData: [],
selectedRowsErpSpuIds: [],
insertRowNumber: 0,
spuSelectDialogVisible: false,
spuDataList: [],
selectedSpuObjs: [],
})
// 定义校验规则
// 表单校验规则
const dataRules = ref({
planCode: [{ required: true, message: "采购计划编号不能为空", trigger: "blur" }],
planDate: [{ required: true, message: "采购计划单据日期不能为空", trigger: "blur" }],
supplierId: [{ required: true, message: "货商不能为空", trigger: "blur" }],
})
// 表格校验规则
// 可编辑表格校验规则
const validRules = ref<VxeTablePropTypes.EditRules<RowVO>>({
planId: [{ required: true, message: "必须填写" }],
totalAmount: [{ required: true, type: "number", min: 18, max: 28, message: "数值范围18~28" }],
unitId: [{ required: true, message: "必须选择" }],
quantity: [{ required: true, type: "number", min: 1, max: 99, message: "数值范围1~99" }],
})
// 表格行勾选
// 获取货商选项
const getSupplierDict = async () => {
try {
const { code, data } = await getSupplierTypeOptions()
if (code === 0) {
supplierDict.value = data
}
} catch (error) {
supplierDict.value = []
}
}
// 获取采购计划编号
const getSequencePlanCode = async () => {
try {
const { code, data } = await getPlanCode()
if (code === 0) {
form.planCode = data
}
} catch (error) {
form.planCode = ""
}
}
// 可编辑表格行勾选
const selectChangeEvent: VxeTableEvents.CheckboxChange<RowVO> = ({ checked }) => {
const $table = tableRef.value
if ($table) {
const records = $table.getCheckboxRecords()
console.log(checked ? "勾选事件" : "取消事件", records)
state.selectedRowsIds = records.map((item) => item.id)
state.selectedRowsErpSpuIds = records.map((item) => item.erpSpuId)
}
}
// 顶部表格行新增
const addEvent = () => {
const newRow: RowVO = {
id: "22",
planId: "",
erpSpuId: "",
merchantId: "",
deptId: "",
quantity: null,
unitPrice: null,
totalAmount: null,
@@ -265,7 +344,6 @@ const addEvent = () => {
unitId: "",
}
state.tableData.unshift(newRow)
state.insertRecords.push(newRow)
nextTick(() => {
const $table = tableRef.value
if ($table) {
@@ -277,11 +355,7 @@ const addEvent = () => {
// 底部表格行新增
const pushEvent = () => {
const newRow: RowVO = {
id: "22",
planId: "",
erpSpuId: "",
merchantId: "",
deptId: "",
quantity: null,
unitPrice: null,
totalAmount: null,
@@ -289,7 +363,6 @@ const pushEvent = () => {
unitId: "",
}
state.tableData.push(newRow)
state.insertRecords.push(newRow)
nextTick(() => {
const $table = tableRef.value
if ($table) {
@@ -301,11 +374,7 @@ const pushEvent = () => {
// 在指定行插入
const insertEvent = () => {
const newRow: RowVO = {
id: "22",
planId: "",
erpSpuId: "",
merchantId: "",
deptId: "",
quantity: null,
unitPrice: null,
totalAmount: null,
@@ -313,7 +382,6 @@ const insertEvent = () => {
unitId: "",
}
state.tableData.splice(state.insertRowNumber, 0, newRow)
state.insertRecords.push(newRow)
nextTick(() => {
const $table = tableRef.value
if ($table) {
@@ -328,13 +396,121 @@ const removeSelectRowEvent = () => {
if ($table) {
const selectRecords = $table.getCheckboxRecords()
if (selectRecords.length > 0) {
state.tableData = state.tableData.filter((item) => !selectRecords.some((row) => row.id === item.id))
state.tableData = state.tableData.filter((item) => !selectRecords.some((row) => row.erpSpuId === item.erpSpuId))
}
}
}
// 点击商品选择
const handleClickSpuSelect = async () => {
state.selectedSpuObjs = [...state.tableData]
state.spuSelectDialogVisible = true
spuListLoading.value = true
try {
const { code, data } = await getCgPlanSpuPage().finally(() => (spuListLoading.value = false))
if (code === 0) {
state.spuDataList = data.records
// 勾选已经选择的商品
const target = state.spuDataList.filter((row: any) =>
state.selectedSpuObjs.some((item: any) => row.id === item.id),
)
target.forEach((row: any) => nextTick(() => spuMultipleTableRef.value!.toggleRowSelection(row)))
}
} catch (error) {
state.spuDataList = []
spuListLoading.value = false
}
}
// 点击商品列表表格行
const rowClick = (row: any) => {
state.selectedSpuObjs.findIndex((item: any) => item.id === row.id) === -1
? // state.selectedSpuObjs.indexOf(row) === -1
state.selectedSpuObjs.push(row)
: state.selectedSpuObjs.splice(
// state.selectedSpuObjs.indexOf(row)
state.selectedSpuObjs.findIndex((item: any) => item.id === row.id),
1,
)
console.log("click-select", state.selectedSpuObjs)
spuMultipleTableRef.value.toggleRowSelection(row)
}
// 选中商品列表表格行
function handleSelect(selectedRows: any[], row: any) {
state.selectedSpuObjs.findIndex((item: any) => item.id === row.id) === -1
? // state.selectedSpuObjs.indexOf(row) === -1
state.selectedSpuObjs.push(row)
: state.selectedSpuObjs.splice(
// state.selectedSpuObjs.indexOf(row)
state.selectedSpuObjs.findIndex((item: any) => item.id === row.id),
1,
)
console.log("check-select", state.selectedSpuObjs)
}
// 全选和反全选商品列表表格行
function handleSelectAll(selectedRows: any[]) {
if (selectedRows.length > 0) {
selectedRows.forEach((row: any) => {
if (state.selectedSpuObjs.findIndex((item: any) => item.id === row.id) === -1) {
state.selectedSpuObjs.push(row)
}
})
} else {
console.log("xxx", selectedRows)
state.spuDataList.forEach((row: any) => {
const index = state.selectedSpuObjs.findIndex((item: any) => item.id === row.id)
if (index !== -1) {
state.selectedSpuObjs.splice(index, 1)
}
})
}
console.log("checkAll-select", state.selectedSpuObjs)
}
// 商品表格多选
const selectionChangeHandle = (objs: any) => {
// console.log("onChange-selects", objs)
}
// 商品选择对话框确认
const handleSelectDialogConfirm = () => {
console.log(state.tableData, state.selectedSpuObjs)
// 对比可编辑表格数据和已勾选的数据判断新勾选的项和取消勾选的项
// 筛选新勾选的项
const addItems = state.selectedSpuObjs
.map((item: any) => ({ ...item, erpSpuId: item.id }))
.filter((item: any) => !state.tableData.some((tableItem: RowVO) => tableItem.id === item.id))
// 仅添加新勾选的项
state.tableData.push(...addItems)
// 筛选取消勾选的项
const removeItems = state.tableData.filter(
(item: any) => !state.selectedSpuObjs.some((selectedItem: any) => selectedItem.id === item.id),
)
// 仅移除取消勾选的项
state.tableData = state.tableData.filter(
(item: any) => !removeItems.some((removeItem: any) => removeItem.id === item.id),
)
// state.tableData.push(item)
// nextTick(() => {
// const $table = tableRef.value
// if ($table) {
// $table.setRow(item)
// }
// })
state.spuSelectDialogVisible = false
console.log("state.tableData", state.tableData)
}
// 提交
const onSubmit = async () => {
console.log(form)
console.log(state.tableData)
// 全量校验
@@ -350,6 +526,11 @@ const onSubmit = async () => {
}
}
}
onMounted(() => {
getSupplierDict()
getSequencePlanCode()
})
// const onSubmit = async () => {
// const valid = await dataFormRef.value.validate().catch(() => {})
// if (!valid) return false