Files
pj_admin_cloud/src/views/supermarketerp/smErpCgPlan/cgPlanOption.vue
T
2025-02-17 15:30:50 +08:00

668 lines
21 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="layout-padding">
<div v-loading="loading" class="layout-padding-auto layout-padding-view" style="overflow: scroll">
<el-form ref="baseDataFormRef" :model="baseDataForm" :rules="dataRules" formDialogRef label-width="140px">
<div class="flex flex-wrap">
<el-form-item label="采购计划编号" prop="planCode">
<el-input v-model.trim="baseDataForm.planCode" placeholder="请输入采购计划编号" disabled style="width: 200px" />
</el-form-item>
<el-form-item label="订单编号" prop="orderNumber">
<el-input v-model.trim="baseDataForm.orderNumber" placeholder="请输入订单编号" maxlength="50" style="width: 200px" />
</el-form-item>
<el-form-item label="采购计划单据日期" prop="planDate">
<el-date-picker
style="width: 200px"
v-model.trim="baseDataForm.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.trim="baseDataForm.supplierId" placeholder="请选择货商" style="width: 200px">
<el-option v-for="item in supplierTypeDict" :key="item?.id" :label="item?.typeName" :value="item?.id" />
</el-select>
</el-form-item>
<!-- <el-form-item label="仓库" prop="warehouseId">
<el-input v-model.trim="baseDataForm.warehouseId" placeholder="请输入仓库id" />
</el-form-item> -->
<el-form-item label="经办人" prop="handlerUserId">
<el-input v-model.trim="baseDataForm.handlerUserId" placeholder="请输入经办人" maxlength="20" style="width: 200px" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model.trim="baseDataForm.remark" placeholder="请输入备注" maxlength="50" style="width: 200px" />
</el-form-item>
</div>
</el-form>
<el-row class="my-3">
<el-button @click="addEvent">新增(顶部)</el-button>
<el-button @click="pushEvent">新增(尾部)</el-button>
<el-button @click="insertEvent">
在第
<el-input-number
@click.stop
v-model="state.insertedRowNumber"
:min="0"
:max="state.editableTableData.length"
:precision="0"
size="small"
controls-position="right"
style="min-width: 50px; margin: 0 5px"
/>
行新增
</el-button>
<el-button @click="removeSelectRowEvent" :disabled="state.selectedRowsErpSpuIds.length <= 0">删除选中</el-button>
<el-button @click="clearData">重置数据</el-button>
<el-button @click="handleClickSpuSelect">商品选择</el-button>
</el-row>
<vxe-table
ref="editableTableRef"
border
:loading="loading"
show-overflow
max-height="400"
:edit-config="{
trigger: 'click',
mode: 'cell',
beforeEditMethod({ row, column }:any) {
// 禁止编辑
if (column.property === '') {
return false
}
return true
},
}"
:column-config="{ resizable: true }"
:row-config="{ isHover: true }"
:resizable-config="{ dragMode: 'fixed' }"
:data="state.editableTableData"
:edit-rules="validRules"
@checkbox-all="selectChangeEvent"
@checkbox-change="selectChangeEvent"
size="mini"
align="center"
>
<vxe-column type="checkbox" width="40" fixed="left" />
<vxe-column type="seq" width="50" fixed="left" />
<!-- <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="productName" title="库存商品" />
<vxe-column field="unitId" title="包装单位" :edit-render="{}">
<template #edit="{ row }">
<el-select v-model="row.unitId" placeholder="请选择包装单位">
<el-option
v-if="row.erpUnitVos?.length > 0"
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="quantity" title="数量" :edit-render="{ autoFocus: 'input', placeholder: '请输入' }">
<template #edit="{ row }">
<el-input v-model="row.quantity" />
</template>
</vxe-column>
<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="累计总金额">
<template #default="{ row }">
{{
row.unitId && row.quantity
? Number(row.erpUnitVos?.find((item: any) => item.id == row.unitId)?.purchasePrice) * row.quantity
: ""
}}
</template>
</vxe-column>
<vxe-column field="remark" title="备注" :edit-render="{ autoFocus: 'input', placeholder: '请输入' }">
<template #edit="{ row }">
<el-input v-model="row.remark" />
</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">
<el-tooltip effect="dark" content="返回列表页面" placement="top">
<el-button type="primary" plain @click="router.back()">取消</el-button>
</el-tooltip>
<el-tooltip effect="dark" content="保存并清空数据" placement="top">
<el-button type="primary" plain @click="onContinueAdd">继续添加</el-button>
</el-tooltip>
<el-tooltip effect="dark" content="保存并返回列表页面" placement="top">
<el-button type="primary" plain @click="onSave">保存</el-button>
</el-tooltip>
</el-row>
<!-- 商品选择对话框 -->
<el-dialog
v-model="state.spuSelectDialogVisible"
title="选择商品"
width="70%"
: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="spuListLoading">确认</el-button>
</div>
</template>
</el-dialog>
</div>
</div>
</template>
<script setup lang="ts" name="SmErpCgPlanDialog">
import { ref, reactive, computed, onMounted } from "vue"
import { useRouter, useRoute } from "vue-router"
import { useDict } from "/@/hooks/dict"
import { useMessage } from "/@/hooks/message"
import { getObj, addObj, putObj, getPlanCode, getCgPlanSpuPage } from "/@/api/supermarketerp/smErpCgPlan"
import { VxeTableEvents, VxeTablePropTypes, type VxeTableInstance } from "vxe-table"
import { getSupplierTypeOptions } from "/@/api/supermarketerp/smErpSupplier"
import { storePrice } from "/@/utils/formatMoney"
// 基本表单数据类型
interface FormVO {
planCode: string
orderNumber: string
planDate: string
supplierId: string
handlerUserId: string
remark: string
[key: string]: string
}
// 可编辑表格行数据类型
interface RowVO {
id?: string
erpSpuId: string
quantity: number | null
unitPrice: number | null
totalAmount: number | null
remark: string
unitId: string
}
const router = useRouter()
const route = useRoute()
const loading = ref(false) // 采购计划加载
const spuListLoading = ref(false) // 对话框商品列表加载
const baseDataFormRef = ref() // 基本数据表单ref
const editableTableRef = ref<VxeTableInstance<RowVO>>() // 可编辑表格ref
const spuMultipleTableRef = ref() // 对话框多选表格ref
const supplierTypeDict = ref<any[]>([]) // 货商下拉选项
// 基本信息表单数据
const baseDataForm = reactive<FormVO>({
planCode: "",
orderNumber: "",
planDate: "",
supplierId: "",
handlerUserId: "",
remark: "",
})
const state = reactive<{
editableTableData: RowVO[]
selectedRowsErpSpuIds: string[]
insertedRowNumber: number
spuSelectDialogVisible: boolean
spuDataList: any[]
selectedSpuObjs: any[]
}>({
editableTableData: [], // 可编辑表格数据
selectedRowsErpSpuIds: [], // 可编辑表格已选行的ErpSpuId
insertedRowNumber: 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>>({
unitId: [{ required: true, message: "必须选择" }],
quantity: [{ required: true, type: "number", min: 1, max: 99, message: "数值范围1~99" }],
})
// 初始化数据
const getInitData = async () => {
const id = route.query.id as string
if (id) {
// 获取数据
loading.value = true
getObj(id)
.then((res: any) => {
Object.assign(baseDataForm, {
planCode: res.data.planCode,
orderNumber: res.data.orderNumber,
planDate: res.data.planDate,
supplierId: res.data.supplierId,
handlerUserId: res.data.handlerUserId,
remark: res.data.remark,
})
state.editableTableData = res.data.items
})
.finally(() => {
loading.value = false
})
}
// 获取货商选项 & 获取采购计划编号
const [supplierTypeOptions, planCode] = await Promise.allSettled([getSupplierTypeOptions(), getPlanCode()]).then((results) =>
results.map((result) => (result.status === "fulfilled" ? result.value : null)),
)
supplierTypeOptions && supplierTypeOptions.code === 0 && (supplierTypeDict.value = supplierTypeOptions.data)
planCode && planCode.code === 0 && (baseDataForm.planCode = planCode.data)
}
// 可编辑表格行勾选
const selectChangeEvent: VxeTableEvents.CheckboxChange<RowVO> = ({ checked }) => {
const $table = editableTableRef.value
if ($table) {
const records = $table.getCheckboxRecords()
console.log(checked ? "勾选事件" : "取消事件", records)
state.selectedRowsErpSpuIds = records.map((item) => item.erpSpuId)
}
}
// 顶部表格行新增
const addEvent = () => {
const newRow: RowVO = {
id: "",
erpSpuId: "",
quantity: null,
unitPrice: null,
totalAmount: null,
remark: "",
unitId: "",
}
state.editableTableData.unshift(newRow)
nextTick(() => {
const $table = editableTableRef.value
if ($table) {
$table.setEditRow(newRow)
}
})
}
// 底部表格行新增
const pushEvent = () => {
const newRow: RowVO = {
erpSpuId: "",
quantity: null,
unitPrice: null,
totalAmount: null,
remark: "",
unitId: "",
}
state.editableTableData.push(newRow)
nextTick(() => {
const $table = editableTableRef.value
if ($table) {
$table.setEditRow(newRow)
}
})
}
// 在指定行插入
const insertEvent = () => {
const newRow: RowVO = {
erpSpuId: "",
quantity: null,
unitPrice: null,
totalAmount: null,
remark: "",
unitId: "",
}
state.editableTableData.splice(state.insertedRowNumber, 0, newRow)
nextTick(() => {
const $table = editableTableRef.value
if ($table) {
$table.setEditRow(newRow)
}
})
}
// 删除选中的行
const removeSelectRowEvent = () => {
const $table = editableTableRef.value
if ($table) {
const selectRecords = $table.getCheckboxRecords()
if (selectRecords.length > 0) {
state.editableTableData = state.editableTableData.filter((item) => !selectRecords.some((row) => row.id === item.id))
}
}
}
// 点击商品选择
const handleClickSpuSelect = async () => {
state.selectedSpuObjs = [...state.editableTableData]
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)
}
// 选中商品列表表格行
const 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)
}
// 全选和反全选商品列表表格行
const 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 {
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 = (rows: any) => {
// console.log("onChange-selects", rows)
}
// 商品选择对话框确认
const handleSelectDialogConfirm = () => {
console.log(state.editableTableData, state.selectedSpuObjs)
// 筛选新勾选的项
const addedItems = state.selectedSpuObjs
.map((item: any) => ({ ...item, erpSpuId: item.id }))
.filter((item: any) => !state.editableTableData.some((editableTableItem: RowVO) => editableTableItem.id === item.id))
// 仅添加新勾选的项
// state.editableTableData.push(...addedItems)
state.editableTableData = [...state.editableTableData, ...addedItems]
// 筛选取消勾选的项
const removedItems = state.editableTableData.filter(
(item: any) => !state.selectedSpuObjs.some((selectedItem: any) => selectedItem.id === item.id),
)
// 仅移除取消勾选的项
state.editableTableData = state.editableTableData.filter(
(item: any) => !removedItems.some((removeItem: any) => removeItem.id === item.id),
)
// state.editableTableData.push(item)
// nextTick(() => {
// const $table = editableTableRef.value
// if ($table) {
// $table.setRow(item)
// }
// })
state.spuSelectDialogVisible = false
console.log("state.editableTableData", state.editableTableData)
}
// 整理数据
const cgPlanSpuItems = computed(() => {
const a = state.editableTableData
return a.map((item: any) => {
console.log("xxxx")
const unit = item.erpUnitVos.find((unitItem: any) => unitItem.id == item.unitId)
return {
id: "",
erpSpuId: item.erpSpuId,
quantity: item.quantity,
unitPrice: unit.purchasePrice ? storePrice(unit?.purchasePrice) : 0,
totalAmount: Number(unit?.purchasePrice || 0) * item.quantity,
remark: item.remark,
unitId: item.unitId,
}
})
})
// 点击继续添加
const onContinueAdd = async () => {
console.log("baseDataForm", baseDataForm)
console.log("state.editableTableData", state.editableTableData)
;(await baseDataFormValidate()) && checkSelectSpu() && (await editableTableValidate()) && (await submitData()) && clearData()
}
// 点击保存
const onSave = async () => {
console.log("baseDataForm", baseDataForm)
console.log("state.editableTableData", state.editableTableData)
;(await baseDataFormValidate()) &&
checkSelectSpu() &&
(await editableTableValidate()) &&
(await submitData()) &&
clearData() &&
router.replace({ path: "/supermarketerp/smErpCgPlan/index" })
}
// 校验基本数据表单 成功返回 true 失败返回 undefined
const baseDataFormValidate = async () => {
const valid = await baseDataFormRef.value.validate().catch(() => {})
return valid
}
// 校验是否选择了商品 成功返回 true 失败返回 false
const checkSelectSpu = () => {
if (state.editableTableData.length <= 0) {
useMessage().warning("请选择商品")
return false
} else {
return true
}
}
// 校验可编辑表格 成功返回 true 失败返回 false
const editableTableValidate = async () => {
// 全量校验
const $table = editableTableRef.value
if ($table) {
const errMap = await $table.validate(true)
if (errMap) {
console.log("全量校验失败!")
return false
} else {
console.log("全量校验成功!")
return true
}
}
}
// 提交数据 成功返回 true 失败返回 false
const submitData = async () => {
try {
loading.value = true
console.log("提交的数据:", {
...baseDataForm,
items: cgPlanSpuItems.value,
})
const res = await addObj({
...baseDataForm,
items: cgPlanSpuItems.value,
}).finally(() => (loading.value = false))
if (res.code === 0) {
useMessage().success("添加成功")
return true
} else {
useMessage().error(res.msg)
return false
}
} catch (err: any) {
useMessage().error(err.msg)
loading.value = false
return false
}
}
// 清空填写的数据 返回 true
const clearData = () => {
for (const key in baseDataForm) {
if (key === "planCode") continue
baseDataForm[key] = ""
}
state.insertedRowNumber = 0
state.editableTableData = []
state.selectedRowsErpSpuIds = []
state.selectedSpuObjs = []
return true
}
onMounted(() => {
getInitData()
})
// const onSubmit = async () => {
// try {
// loading.value = true
// form.id ? await putObj(form) : await addObj(form)
// useMessage().success(form.id ? "修改成功" : "添加成功")
// } catch (err: any) {
// useMessage().error(err.msg)
// } finally {
// loading.value = false
// }
// }
</script>