<template>
|
<div class="app-container">
|
<div class="search_form">
|
<div>
|
<span class="search_title">出库时间:</span>
|
<el-date-picker
|
v-model="searchForm.timeStr"
|
type="date"
|
placeholder="请选择日期"
|
value-format="YYYY-MM-DD"
|
format="YYYY-MM-DD"
|
clearable
|
@change="handleQuery"
|
/>
|
<span class="search_title ml10">产品名称:</span>
|
<el-input v-model="searchForm.productName" style="width: 240px" placeholder="请输入" @change="handleQuery"
|
clearable prefix-icon="Search" />
|
<span class="search_title ml10">来源:</span>
|
<el-select v-model="searchForm.recordType"
|
style="width: 240px"
|
placeholder="请选择"
|
clearable
|
@change="handleQuery">
|
<el-option v-for="item in stockRecordTypeOptions"
|
:key="item.value"
|
:label="item.label"
|
:value="item.value"/>
|
</el-select>
|
<el-button type="primary" @click="handleQuery" style="margin-left: 10px">搜索</el-button>
|
</div>
|
<div>
|
<el-button @click="handleOut">导出</el-button>
|
</div>
|
</div>
|
<div class="table_list">
|
<el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange"
|
:expand-row-keys="expandedRowKeys" :row-key="(row, index) => index" style="width: 100%"
|
:row-class-name="tableRowClassName" height="calc(100vh - 18.5em)">
|
<el-table-column align="center" type="selection" width="55" />
|
<el-table-column align="center" label="序号" type="index" width="60" />
|
<el-table-column label="产品大类" prop="productName" show-overflow-tooltip />
|
<el-table-column label="规格型号" prop="model" show-overflow-tooltip />
|
<el-table-column label="单位" prop="unit" show-overflow-tooltip />
|
<el-table-column label="合格库存数量" prop="qualifiedQuantity" show-overflow-tooltip />
|
<el-table-column label="不合格库存数量" prop="unQualifiedQuantity" show-overflow-tooltip />
|
<el-table-column label="合格冻结数量" prop="qualifiedLockedQuantity" show-overflow-tooltip />
|
<el-table-column label="不合格冻结数量" prop="unQualifiedLockedQuantity" show-overflow-tooltip />
|
<el-table-column label="库存预警数量" prop="warnNum" show-overflow-tooltip />
|
<el-table-column label="备注" prop="remark" show-overflow-tooltip />
|
<el-table-column label="最近更新时间" prop="updateTime" show-overflow-tooltip />
|
<el-table-column fixed="right" label="操作" min-width="90" align="center">
|
<template #default="scope">
|
<el-button link type="primary" @click="showSubtractModal(scope.row)" :disabled="scope.row.unQualifiedUnLockedQuantity === 0 && scope.row.qualifiedUnLockedQuantity === 0">{{ actionButtonText }}</el-button>
|
<el-button link type="primary" v-if="scope.row.unQualifiedUnLockedQuantity > 0 || scope.row.qualifiedUnLockedQuantity > 0" @click="showFrozenModal(scope.row)">冻结</el-button>
|
<el-button link type="primary" v-if="scope.row.qualifiedLockedQuantity > 0 || scope.row.unQualifiedLockedQuantity > 0" @click="showThawModal(scope.row)">解冻</el-button>
|
</template>
|
</el-table-column>
|
</el-table>
|
<pagination v-show="total > 0" :total="total" layout="total, sizes, prev, pager, next, jumper"
|
:page="page.current" :limit="page.size" @pagination="paginationChange" />
|
</div>
|
|
<!-- 领用/发货弹框 -->
|
<el-dialog
|
v-model="isShowSubtractModal"
|
:title="dialogTitle"
|
width="800"
|
@close="closeSubtractModal"
|
>
|
<el-form label-width="140px" :model="subtractForm" label-position="top" ref="subtractFormRef">
|
<el-form-item
|
label="产品名称"
|
prop="productModelId"
|
:rules="[{ required: true, message: '请选择产品', trigger: 'change' }]"
|
>
|
<el-button type="primary" disabled>
|
{{ subtractForm.productName ? subtractForm.productName : '选择产品' }}
|
</el-button>
|
</el-form-item>
|
|
<el-form-item label="规格" prop="productModelName">
|
<el-input v-model="subtractForm.model" disabled />
|
</el-form-item>
|
|
<el-form-item label="单位" prop="unit">
|
<el-input v-model="subtractForm.unit" disabled />
|
</el-form-item>
|
|
<el-form-item
|
label="库存类型"
|
prop="type"
|
:rules="[{ required: true, message: '请选择库存类型', trigger: 'change' }]"
|
>
|
<el-select v-model="subtractForm.type" placeholder="请选择库存类型" @change="handleTypeChange">
|
<el-option label="合格库存" value="qualified" :disabled="currentRecord.qualifiedUnLockedQuantity <= 0" />
|
<el-option label="不合格库存" value="unqualified" :disabled="currentRecord.unQualifiedUnLockedQuantity <= 0" />
|
</el-select>
|
</el-form-item>
|
|
<el-form-item label="数量" prop="qualitity">
|
<el-input-number v-model="subtractForm.qualitity" :step="1" :min="1" :max="maxQuality" style="width: 100%" />
|
</el-form-item>
|
|
<el-form-item label="备注" prop="remark">
|
<el-input v-model="subtractForm.remark" type="textarea" />
|
</el-form-item>
|
</el-form>
|
<template #footer>
|
<div class="dialog-footer">
|
<el-button type="primary" @click="handleSubtractSubmit">确认</el-button>
|
<el-button @click="closeSubtractModal">取消</el-button>
|
</div>
|
</template>
|
</el-dialog>
|
|
<!-- 冻结/解冻弹框 -->
|
<el-dialog
|
v-model="isShowFrozenModal"
|
:title="frozenDialogTitle"
|
width="800"
|
@close="closeFrozenModal"
|
>
|
<el-form label-width="140px" :model="frozenForm" label-position="top" ref="frozenFormRef">
|
<el-form-item
|
label="产品名称"
|
prop="productModelId"
|
:rules="[{ required: true, message: '请选择产品', trigger: 'change' }]"
|
>
|
<el-button type="primary" disabled>
|
{{ frozenForm.productName ? frozenForm.productName : '选择产品' }}
|
</el-button>
|
</el-form-item>
|
|
<el-form-item label="规格" prop="productModelName">
|
<el-input v-model="frozenForm.model" disabled />
|
</el-form-item>
|
|
<el-form-item label="单位" prop="unit">
|
<el-input v-model="frozenForm.unit" disabled />
|
</el-form-item>
|
|
<el-form-item
|
label="库存类型"
|
prop="type"
|
:rules="[{ required: true, message: '请选择库存类型', trigger: 'change' }]"
|
>
|
<el-select v-model="frozenForm.type" placeholder="请选择库存类型" @change="handleFrozenTypeChange">
|
<el-option
|
label="合格库存"
|
value="qualified"
|
:disabled="frozenOperationType === 'frozen' ? currentRecord.qualifiedUnLockedQuantity <= 0 : currentRecord.qualifiedLockedQuantity <= 0"
|
/>
|
<el-option
|
label="不合格库存"
|
value="unqualified"
|
:disabled="frozenOperationType === 'frozen' ? currentRecord.unQualifiedUnLockedQuantity <= 0 : currentRecord.unQualifiedLockedQuantity <= 0"
|
/>
|
</el-select>
|
</el-form-item>
|
|
<el-form-item label="数量" prop="qualitity">
|
<el-input-number v-model="frozenForm.qualitity" :step="1" :min="1" :max="frozenMaxQuality" style="width: 100%" />
|
</el-form-item>
|
|
<el-form-item label="备注" prop="remark">
|
<el-input v-model="frozenForm.remark" type="textarea" />
|
</el-form-item>
|
</el-form>
|
<template #footer>
|
<div class="dialog-footer">
|
<el-button type="primary" @click="handleFrozenSubmit">确认</el-button>
|
<el-button @click="closeFrozenModal">取消</el-button>
|
</div>
|
</template>
|
</el-dialog>
|
</div>
|
</template>
|
|
<script setup>
|
import pagination from '@/components/PIMTable/Pagination.vue'
|
import { ref, reactive, toRefs, getCurrentInstance, onMounted, computed } from 'vue'
|
import { ElMessageBox } from "element-plus";
|
import useUserStore from '@/store/modules/user'
|
import { userListNoPageByTenantId } from "@/api/system/user.js";
|
import {
|
getStockInventoryListPageCombined
|
} from "@/api/inventoryManagement/stockInventory.js";
|
import {
|
subtractStockInventory
|
} from "@/api/inventoryManagement/stockInventory.js";
|
import {
|
subtractStockUnInventory
|
} from "@/api/inventoryManagement/stockUninventory.js";
|
import {
|
frozenStockInventory,
|
thawStockInventory
|
} from "@/api/inventoryManagement/stockInventory.js";
|
import {
|
frozenStockUninventory,
|
thawStockUninventory
|
} from "@/api/inventoryManagement/stockUninventory.js";
|
import { getCurrentDate } from "@/utils/index.js";
|
import {
|
findAllQualifiedStockOutRecordTypeOptions, findAllUnQualifiedStockOutRecordTypeOptions,
|
} from "@/api/basicData/enum.js";
|
|
const props = defineProps({
|
productId: {
|
type: [String, Number],
|
default: ''
|
},
|
productName: {
|
type: String,
|
default: ''
|
}
|
})
|
|
const userStore = useUserStore()
|
const { proxy } = getCurrentInstance()
|
const tableData = ref([])
|
const selectedRows = ref([])
|
const userList = ref([])
|
const tableLoading = ref(false)
|
// 来源类型选项
|
const stockRecordTypeOptions = ref([])
|
const page = reactive({
|
current: 1,
|
size: 100,
|
})
|
const total = ref(0)
|
|
// 当前操作的记录
|
const currentRecord = ref({})
|
|
// 是否显示领用/发货弹框
|
const isShowSubtractModal = ref(false)
|
// 是否显示冻结/解冻弹框
|
const isShowFrozenModal = ref(false)
|
// 冻结/解冻操作类型
|
const frozenOperationType = ref('frozen')
|
|
// 判断是否是成品(产品名称包含"成品")
|
const isFinishedProduct = computed(() => {
|
return props.productName && props.productName.includes('成品')
|
})
|
|
// 按钮文字:成品显示"发货",其他显示"领用"
|
const actionButtonText = computed(() => {
|
return isFinishedProduct.value ? '发货' : '领用'
|
})
|
|
// 弹框标题
|
const dialogTitle = computed(() => {
|
return isFinishedProduct.value ? '发货' : '领用'
|
})
|
|
// 冻结/解冻弹框标题
|
const frozenDialogTitle = computed(() => {
|
return frozenOperationType.value === 'frozen' ? '冻结' : '解冻'
|
})
|
|
// 领用/发货表单
|
const subtractFormRef = ref(null)
|
const subtractForm = ref({
|
productId: undefined,
|
productModelId: undefined,
|
productName: "",
|
model: "",
|
unit: "",
|
type: "",
|
qualitity: 0,
|
remark: '',
|
})
|
|
// 冻结/解冻表单
|
const frozenFormRef = ref(null)
|
const frozenForm = ref({
|
productId: undefined,
|
productModelId: undefined,
|
productName: "",
|
model: "",
|
unit: "",
|
type: "",
|
qualitity: 0,
|
remark: '',
|
})
|
|
// 领用/发货最大数量
|
const maxQuality = computed(() => {
|
let max = 0;
|
if (subtractForm.value.type === 'qualified') {
|
max = currentRecord.value.qualifiedUnLockedQuantity ? currentRecord.value.qualifiedUnLockedQuantity : 0;
|
} else {
|
max = currentRecord.value.unQualifiedUnLockedQuantity ? currentRecord.value.unQualifiedUnLockedQuantity : 0;
|
}
|
return Math.max(max, 1);
|
})
|
|
// 冻结/解冻最大数量
|
const frozenMaxQuality = computed(() => {
|
let max = 0;
|
if (frozenOperationType.value === 'frozen') {
|
if (frozenForm.value.type === 'qualified') {
|
max = currentRecord.value.qualifiedUnLockedQuantity ? currentRecord.value.qualifiedUnLockedQuantity : 0;
|
} else {
|
max = currentRecord.value.unQualifiedUnLockedQuantity ? currentRecord.value.unQualifiedUnLockedQuantity : 0;
|
}
|
} else {
|
if (frozenForm.value.type === 'qualified') {
|
max = currentRecord.value.qualifiedLockedQuantity ? currentRecord.value.qualifiedLockedQuantity : 0;
|
} else {
|
max = currentRecord.value.unQualifiedLockedQuantity ? currentRecord.value.unQualifiedLockedQuantity : 0;
|
}
|
}
|
return Math.max(max, 1);
|
})
|
|
// 用户信息表单弹框数据
|
const dialogFormVisible = ref(false)
|
const data = reactive({
|
searchForm: {
|
productName: '',
|
recordType: '',
|
timeStr: '',
|
topParentProductId: props.productId,
|
},
|
form: {
|
productrecordId: '',
|
},
|
rules: {
|
inboundTime: [{ required: true, message: "请选择", trigger: "change" }],
|
inboundQuantity: [{ required: true, message: "请输入", trigger: "blur" }],
|
nickname: [{ required: true, message: "请选择", trigger: "change" }]
|
}
|
})
|
const { searchForm, form, rules } = toRefs(data)
|
|
// 查询列表
|
/** 搜索按钮操作 */
|
const handleQuery = () => {
|
page.current = 1
|
getList()
|
}
|
const paginationChange = (obj) => {
|
page.current = obj.page;
|
page.size = obj.limit;
|
getList()
|
}
|
const getList = () => {
|
tableLoading.value = true
|
getStockInventoryListPageCombined({ ...searchForm.value, ...page }).then(res => {
|
tableLoading.value = false
|
tableData.value = res.data.records
|
total.value = res.data.total
|
}).catch(() => {
|
tableLoading.value = false
|
})
|
}
|
|
// 获取来源类型选项
|
const fetchStockRecordTypeOptions = () => {
|
Promise.all([
|
findAllQualifiedStockOutRecordTypeOptions(),
|
findAllUnQualifiedStockOutRecordTypeOptions()
|
]).then(([qualifiedRes, unQualifiedRes]) => {
|
const qualified = qualifiedRes.data || [];
|
const unQualified = unQualifiedRes.data || [];
|
const allOptions = [...qualified, ...unQualified];
|
const uniqueOptions = allOptions.filter((item, index, self) =>
|
index === self.findIndex((t) => t.value === item.value)
|
);
|
stockRecordTypeOptions.value = uniqueOptions;
|
});
|
}
|
|
// 点击领用/发货
|
const showSubtractModal = (row) => {
|
currentRecord.value = row
|
subtractForm.value = {
|
...row,
|
type: '',
|
qualitity: 0,
|
remark: '',
|
}
|
isShowSubtractModal.value = true
|
}
|
|
// 关闭领用/发货弹框
|
const closeSubtractModal = () => {
|
subtractForm.value = {
|
productId: undefined,
|
productModelId: undefined,
|
productName: "",
|
model: "",
|
unit: "",
|
type: "",
|
qualitity: 0,
|
remark: '',
|
}
|
isShowSubtractModal.value = false
|
}
|
|
// 库存类型改变
|
const handleTypeChange = () => {
|
subtractForm.value.qualitity = 0;
|
}
|
|
// 冻结类型改变
|
const handleFrozenTypeChange = () => {
|
frozenForm.value.qualitity = 0;
|
}
|
|
// 提交领用/发货
|
const handleSubtractSubmit = () => {
|
proxy.$refs["subtractFormRef"].validate(valid => {
|
if (valid) {
|
if (!subtractForm.value.productModelId) {
|
proxy.$modal.msgError("请选择产品");
|
return;
|
}
|
if (subtractForm.value.type === 'qualified') {
|
subtractStockInventory(subtractForm.value).then(res => {
|
isShowSubtractModal.value = false;
|
proxy.$modal.msgSuccess("提交成功");
|
getList();
|
})
|
} else {
|
subtractStockUnInventory(subtractForm.value).then(res => {
|
isShowSubtractModal.value = false;
|
proxy.$modal.msgSuccess("提交成功");
|
getList();
|
})
|
}
|
}
|
})
|
}
|
|
// 点击冻结
|
const showFrozenModal = (row) => {
|
currentRecord.value = row
|
frozenOperationType.value = 'frozen'
|
frozenForm.value = {
|
...row,
|
type: '',
|
qualitity: 0,
|
remark: '',
|
}
|
isShowFrozenModal.value = true
|
}
|
|
// 点击解冻
|
const showThawModal = (row) => {
|
currentRecord.value = row
|
frozenOperationType.value = 'thaw'
|
frozenForm.value = {
|
...row,
|
type: '',
|
qualitity: 0,
|
remark: '',
|
}
|
isShowFrozenModal.value = true
|
}
|
|
// 关闭冻结/解冻弹框
|
const closeFrozenModal = () => {
|
frozenForm.value = {
|
productId: undefined,
|
productModelId: undefined,
|
productName: "",
|
model: "",
|
unit: "",
|
type: "",
|
qualitity: 0,
|
remark: '',
|
}
|
isShowFrozenModal.value = false
|
}
|
|
// 提交冻结/解冻
|
const handleFrozenSubmit = () => {
|
proxy.$refs["frozenFormRef"].validate(valid => {
|
if (valid) {
|
if (!frozenForm.value.productModelId) {
|
proxy.$modal.msgError("请选择产品");
|
return;
|
}
|
const isQualified = frozenForm.value.type === 'qualified'
|
const isFrozen = frozenOperationType.value === 'frozen'
|
|
if (isQualified) {
|
if (isFrozen) {
|
frozenStockInventory(frozenForm.value).then(res => {
|
isShowFrozenModal.value = false;
|
proxy.$modal.msgSuccess("冻结成功");
|
getList();
|
})
|
} else {
|
thawStockInventory(frozenForm.value).then(res => {
|
isShowFrozenModal.value = false;
|
proxy.$modal.msgSuccess("解冻成功");
|
getList();
|
})
|
}
|
} else {
|
if (isFrozen) {
|
frozenStockUninventory(frozenForm.value).then(res => {
|
isShowFrozenModal.value = false;
|
proxy.$modal.msgSuccess("冻结成功");
|
getList();
|
})
|
} else {
|
thawStockUninventory(frozenForm.value).then(res => {
|
isShowFrozenModal.value = false;
|
proxy.$modal.msgSuccess("解冻成功");
|
getList();
|
})
|
}
|
}
|
}
|
})
|
}
|
|
// 表格选择数据
|
const handleSelectionChange = (selection) => {
|
selectedRows.value = selection.filter(item => item.id);
|
}
|
const expandedRowKeys = ref([])
|
|
// 表格行类名
|
const tableRowClassName = ({ row }) => {
|
const stock = Number(row?.qualifiedUnLockedQuantity ?? 0);
|
const warn = Number(row?.warnNum ?? 0);
|
if (!Number.isFinite(stock) || !Number.isFinite(warn)) {
|
return '';
|
}
|
return stock < warn ? 'row-low-stock' : '';
|
};
|
|
// 导出
|
const handleOut = () => {
|
ElMessageBox.confirm(
|
'是否确认导出?',
|
'导出', {
|
confirmButtonText: '确认',
|
cancelButtonText: '取消',
|
type: 'warning',
|
}
|
).then(() => {
|
proxy.download("/stockInventory/exportStockInventory", {topParentProductId: props.productId}, '库存信息.xlsx')
|
}).catch(() => {
|
proxy.$modal.msg("已取消")
|
})
|
}
|
|
onMounted(() => {
|
getList()
|
fetchStockRecordTypeOptions()
|
})
|
</script>
|
|
<style scoped lang="scss">
|
:deep(.row-low-stock td) {
|
background-color: #fde2e2;
|
color: #c45656;
|
}
|
|
:deep(.row-low-stock:hover > td) {
|
background-color: #fcd4d4;
|
}
|
</style>
|