feat(biz): 添加生产订单管理功能

This commit is contained in:
zxy 2026-05-18 15:37:11 +08:00
parent dc19a31ba5
commit bba176ebec

View File

@ -0,0 +1,285 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible" width="1400px">
<div class="dialog-content">
<div class="table-container">
<!-- 表1物料搜索列表 -->
<div class="table-section">
<!-- 搜索区域 -->
<el-form :model="queryParams" inline label-width="80px" class="search-form">
<el-form-item label="检索条件">
<el-input
v-model="queryParams.searchText"
placeholder="物料编码、物料名称支持模糊查询"
clearable
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="searchMaterial">
<Icon icon="ep:search" class="mr-5px" />搜索
</el-button>
<el-button @click="resetQuery">
<Icon icon="ep:refresh-right" class="mr-5px" />重置
</el-button>
</el-form-item>
</el-form>
<!-- 表格区域 -->
<el-table
ref="tableRef"
v-loading="loading"
:data="materialList"
:show-overflow-tooltip="true"
border
class="material-table"
@row-click="handleRowClick"
>
<el-table-column type="selection" width="50px" align="center" />
<el-table-column label="序号" width="60px" align="center" type="index" />
<el-table-column label="物料编码" align="center" prop="matCode" width="120px" />
<el-table-column label="物料名称" align="center" prop="matName" width="150px" />
<el-table-column label="规格型号" align="center" prop="spec" width="120px" />
<el-table-column label="单位" align="center" prop="unit" width="80px" />
</el-table>
<!-- 分页 -->
<Pagination
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
:total="total"
@pagination="searchMaterial"
class="mt-15px"
/>
</div>
<!-- 表2已选中物料列表 -->
<div class="table-section">
<div class="section-header">
<div class="action-buttons">
<el-button size="small" @click="clearSelected">清空</el-button>
<el-button size="small" type="danger" @click="removeSelected">删除行</el-button>
</div>
</div>
<!-- 表格区域 -->
<el-table
ref="selectedTableRef"
:data="selectedList"
:show-overflow-tooltip="true"
border
class="material-table"
@row-click="handleSelectedRowClick"
>
<el-table-column type="selection" width="50px" align="center" />
<el-table-column label="序号" width="60px" align="center" type="index" />
<el-table-column label="物料编码" align="center" prop="matCode" width="120px" />
<el-table-column label="物料名称" align="center" prop="matName" width="150px" />
<el-table-column label="规格型号" align="center" prop="spec" width="120px" />
<el-table-column label="单位" align="center" prop="unit" width="80px" />
</el-table>
</div>
</div>
</div>
<template #footer>
<el-button @click="confirmSelection" type="primary">保存</el-button>
<el-button @click="dialogVisible = false">取消</el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { ref, reactive, nextTick } from 'vue'
import * as MaterialApi from '@/api/biz/material'
import { Icon } from '@/components/Icon'
const message = useMessage()
const dialogVisible = ref(false)
const dialogTitle = ref('选择物料')
const loading = ref(false)
const total = ref(0)
const materialList = ref([])
const selectedList = ref<any[]>([])
const tableRef = ref()
const selectedTableRef = ref()
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
searchText: undefined,
matType: '1'
})
const emit = defineEmits(['confirm'])
//
const searchMaterial = async () => {
loading.value = true
try {
const params: any = {
pageNo: queryParams.pageNo,
pageSize: queryParams.pageSize,
matType: queryParams.matType
}
if (queryParams.searchText) {
params.keyWord = queryParams.searchText
}
const data = await MaterialApi.getMaterialPage(params)
materialList.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
//
const resetQuery = () => {
queryParams.searchText = undefined
queryParams.pageNo = 1
searchMaterial()
}
//
const handleRowClick = (row: any) => {
if (tableRef.value) {
tableRef.value.toggleRowSelection(row)
const selectedItems = tableRef.value.getSelectionRows()
//
selectedItems.forEach(item => {
if (!selectedList.value.some(s => s.id === item.id)) {
selectedList.value.push({
id: item.id,
matCode: item.matCode,
matName: item.matName,
spec: item.spec,
unit: item.unit,
materialId: item.id,
materialCode: item.matCode,
materialName: item.matName
})
}
})
//
const selectedIds = selectedItems.map(i => i.id)
selectedList.value = selectedList.value.filter(item => selectedIds.includes(item.id))
}
}
//
const handleSelectedRowClick = (row: any) => {
if (selectedTableRef.value) {
selectedTableRef.value.toggleRowSelection(row)
}
}
//
const clearSelected = () => {
selectedList.value = []
// 1
nextTick(() => {
if (tableRef.value) {
tableRef.value.clearSelection()
}
})
}
//
const removeSelected = () => {
if (!selectedTableRef.value) return
const selectedItems = selectedTableRef.value.getSelectionRows()
if (selectedItems.length === 0) {
message.warning('请选择要删除的行')
return
}
const selectedIds = selectedItems.map(item => item.id)
selectedList.value = selectedList.value.filter(item => !selectedIds.includes(item.id))
// 1
nextTick(() => {
if (tableRef.value) {
materialList.value.forEach(item => {
if (selectedIds.includes(item.id)) {
tableRef.value.toggleRowSelection(item, false)
}
})
}
})
}
//
const confirmSelection = () => {
if (selectedList.value.length === 0) {
message.warning('请选择物料')
return
}
emit('confirm', selectedList.value)
dialogVisible.value = false
}
//
const open = () => {
dialogVisible.value = true
selectedList.value = []
searchMaterial()
}
defineExpose({ open })
</script>
<style scoped>
.dialog-content {
padding: 15px;
}
.table-container {
display: flex;
gap: 20px;
height: 500px;
}
.table-section {
flex: 1;
display: flex;
flex-direction: column;
background: #fff;
border: 1px solid #e4e7ed;
border-radius: 8px;
overflow: hidden;
}
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 15px;
background: #f5f7fa;
border-bottom: 1px solid #e4e7ed;
}
.action-buttons {
display: flex;
gap: 8px;
}
.search-form {
padding: 15px;
border-bottom: 1px solid #e4e7ed;
}
.material-table {
flex: 1;
min-height: 0;
}
:deep(.el-table__header-wrapper) {
position: sticky;
top: 0;
z-index: 1;
}
</style>