merge: pull remote master and keep local dispatch remain qty logic
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
commit
d4f2465fc6
111
src/api/defectiveWarehouse.ts
Normal file
111
src/api/defectiveWarehouse.ts
Normal file
@ -0,0 +1,111 @@
|
||||
import { request } from '@/utils/request'
|
||||
|
||||
// 不良品库 类型定义
|
||||
export interface DefectiveWarehouse {
|
||||
id?: number
|
||||
|
||||
processId?: number
|
||||
|
||||
sourceOrderId?: number
|
||||
|
||||
inboundCode?: string
|
||||
|
||||
subjectName?: string
|
||||
|
||||
inboundType?: number
|
||||
|
||||
processPlanId?: number
|
||||
|
||||
warehouseId?: number
|
||||
|
||||
status?: number
|
||||
|
||||
deleted?: number
|
||||
|
||||
businessType?: string
|
||||
|
||||
num?:number
|
||||
}
|
||||
|
||||
export const STOCK_IN_TYPE_MAP: Record<number, { label: string; type: 'default' | 'info' | 'success' | 'warning' | 'error' }> = {
|
||||
1: { label: '生产入库', type: 'success' },
|
||||
2: { label: '委外收货', type: 'warning' },
|
||||
3: { label: '采购入库', type: 'info' },
|
||||
}
|
||||
|
||||
export const STOCK_IN_STATUS_MAP: Record<number, { label: string; type: 'default' | 'info' | 'success' | 'warning' | 'error' }> = {
|
||||
0: { label: '草稿', type: 'default' },
|
||||
1: { label: '待确认', type: 'info' },
|
||||
2: { label: '上架入库', type: 'success' },
|
||||
3: { label: '已撤回', type: 'warning' },
|
||||
}
|
||||
|
||||
|
||||
// 不良品库 API
|
||||
export const defectiveWarehouseApi = {
|
||||
// 分页查询
|
||||
page(params: { page: number; pageSize: number; id?: number; status?: number }) {
|
||||
return request({ url: '/biz/defectiveWarehouse/page', method: 'get', params })
|
||||
},
|
||||
|
||||
// 获取详情
|
||||
detail(id: number) {
|
||||
return request({ url: `/biz/defectiveWarehouse/${id}`, method: 'get' })
|
||||
},
|
||||
|
||||
// 新增
|
||||
create(data: DefectiveWarehouse) {
|
||||
return request({ url: '/biz/defectiveWarehouse', method: 'post', data })
|
||||
},
|
||||
|
||||
// 修改
|
||||
update(data: DefectiveWarehouse) {
|
||||
return request({ url: '/biz/defectiveWarehouse', method: 'put', data })
|
||||
},
|
||||
|
||||
// 删除
|
||||
delete(ids: number[]) {
|
||||
return request({ url: `/biz/defectiveWarehouse/${ids.join(',')}`, method: 'delete' })
|
||||
},
|
||||
|
||||
// 导出
|
||||
export(params?: { ids?: number[]; id?: number; status?: number }) {
|
||||
const p: Record<string, any> = {}
|
||||
if (params?.ids?.length) p.ids = params.ids.join(',')
|
||||
if (params?.id !== undefined && params?.id !== null) p.id = params.id
|
||||
if (params?.status !== undefined && params?.status !== null) p.status = params.status
|
||||
return request({ url: `/biz/defectiveWarehouse/export`, method: 'get', params: p, responseType: 'blob' })
|
||||
},
|
||||
|
||||
// 导入
|
||||
importData(file: File) {
|
||||
const formData = new FormData()
|
||||
formData.append('file', file)
|
||||
return request<{ success: number; fail: number; errors: string[] }>({
|
||||
url: `/biz/defectiveWarehouse/import`,
|
||||
method: 'post',
|
||||
data: formData,
|
||||
headers: { 'Content-Type': 'multipart/form-data' }
|
||||
})
|
||||
},
|
||||
|
||||
// 下载导入模板
|
||||
downloadTemplate() {
|
||||
return request({ url: `/biz/defectiveWarehouse/template`, method: 'get', responseType: 'blob' })
|
||||
},
|
||||
|
||||
//确认入库
|
||||
confirm(id:number) {
|
||||
return request({
|
||||
url:`/biz/defectiveWarehouse/confirm/${id}`,
|
||||
method:"get"
|
||||
})
|
||||
},
|
||||
//撤回入库
|
||||
cancel(id:number) {
|
||||
return request({
|
||||
url:`/biz/defectiveWarehouse/cancel/${id}`,
|
||||
method:"get"
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -976,7 +976,7 @@ const selectedDeviceIds = ref<any>([])
|
||||
|
||||
function handlerConnectionDevice(row:any) {
|
||||
deviceDocumentConnectionVisible.value = true
|
||||
title.value = row.deviceName + "设备工艺文档关联"
|
||||
title.value = row.ncName + "关联设备"
|
||||
deviceDocumentConnection.sourceId = row.id
|
||||
getDeviceList(deviceDocumentConnection.sourceId)
|
||||
}
|
||||
|
||||
572
src/views/biz/defectiveWarehouse/index.vue
Normal file
572
src/views/biz/defectiveWarehouse/index.vue
Normal file
@ -0,0 +1,572 @@
|
||||
<template>
|
||||
<div class="page-container">
|
||||
<n-card>
|
||||
<!-- 搜索表单 -->
|
||||
<div class="search-form">
|
||||
<n-form inline :model="searchForm" label-placement="left">
|
||||
<n-form-item label="状态">
|
||||
<n-select v-model:value="searchForm.status" placeholder="请选择状态" clearable style="width: 150px"
|
||||
:options="statusOptions"/>
|
||||
</n-form-item>
|
||||
<n-form-item>
|
||||
<n-space>
|
||||
<n-button type="primary" @click="handleSearch">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<SearchOutline/>
|
||||
</n-icon>
|
||||
</template>
|
||||
搜索
|
||||
</n-button>
|
||||
<n-button @click="handleReset">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<RefreshOutline/>
|
||||
</n-icon>
|
||||
</template>
|
||||
重置
|
||||
</n-button>
|
||||
</n-space>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
</div>
|
||||
|
||||
<!-- 工具栏 -->
|
||||
<div class="table-toolbar">
|
||||
<n-space>
|
||||
<!-- <n-button type="primary" @click="handleAdd">-->
|
||||
<!-- <template #icon><n-icon><AddOutline /></n-icon></template>-->
|
||||
<!-- 新增-->
|
||||
<!-- </n-button>-->
|
||||
<n-button @click="importModalVisible = true">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<CloudUploadOutline/>
|
||||
</n-icon>
|
||||
</template>
|
||||
导入
|
||||
</n-button>
|
||||
<n-button @click="handleExport">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<DownloadOutline/>
|
||||
</n-icon>
|
||||
</template>
|
||||
导出{{ selectedIds.length > 0 ? `(${selectedIds.length})` : '' }}
|
||||
</n-button>
|
||||
<n-button type="error" :disabled="selectedIds.length === 0" @click="handleBatchDelete">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<TrashOutline/>
|
||||
</n-icon>
|
||||
</template>
|
||||
删除
|
||||
</n-button>
|
||||
</n-space>
|
||||
</div>
|
||||
|
||||
<!-- 表格 -->
|
||||
<n-data-table
|
||||
:columns="columns"
|
||||
:data="tableData"
|
||||
:loading="loading"
|
||||
:pagination="pagination"
|
||||
:row-key="(row) => row.id"
|
||||
:scroll-x="1200"
|
||||
@update:page="handlePageChange"
|
||||
@update:page-size="handlePageSizeChange"
|
||||
@update:checked-row-keys="handleCheck"
|
||||
/>
|
||||
</n-card>
|
||||
|
||||
<!-- 新增/编辑弹窗 -->
|
||||
<n-modal v-model:show="modalVisible" preset="card" :title="modalTitle" style="width: 600px">
|
||||
<n-form ref="formRef" :model="formData" :rules="formRules" label-placement="left" label-width="100px">
|
||||
<n-form-item label="入库单号" path="inboundCode">
|
||||
<n-input v-model:value="formData.inboundCode" disabled placeholder="请输入入库单号 OWR-yyyyMMdd-0001"/>
|
||||
</n-form-item>
|
||||
<n-form-item label="入库类型" path="inboundType">
|
||||
<n-select v-model:value="formData.inboundType" placeholder="请选择入库类型"
|
||||
:options="typeOptions"/>
|
||||
</n-form-item>
|
||||
<n-form-item label="入库数量" path="num">
|
||||
<n-input-number v-model:value="formData.num" :min="0.0001" :precision="4" style="width: 100%" />
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
<template #footer>
|
||||
<n-space justify="end">
|
||||
<n-button @click="modalVisible = false">取消</n-button>
|
||||
<n-button type="primary" @click="handleSubmit">确定</n-button>
|
||||
</n-space>
|
||||
</template>
|
||||
</n-modal>
|
||||
|
||||
<!-- 导入弹窗 -->
|
||||
<n-modal v-model:show="importModalVisible" preset="card" title="导入不良品库" style="width: 500px">
|
||||
<n-space vertical>
|
||||
<n-alert type="info">
|
||||
<template #header>导入说明</template>
|
||||
<ul style="margin: 0; padding-left: 16px; line-height: 1.8">
|
||||
<li>请先下载导入模板,按模板格式填写数据</li>
|
||||
<li>支持 .xlsx 或 .xls 格式</li>
|
||||
</ul>
|
||||
</n-alert>
|
||||
<n-space>
|
||||
<n-button type="primary" @click="handleDownloadTemplate">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<DownloadOutline/>
|
||||
</n-icon>
|
||||
</template>
|
||||
下载模板
|
||||
</n-button>
|
||||
</n-space>
|
||||
<n-upload :max="1" accept=".xlsx,.xls" :show-file-list="true" :custom-request="handleImportUpload">
|
||||
<n-upload-dragger>
|
||||
<div style="margin-bottom: 12px">
|
||||
<n-icon size="48" :depth="3">
|
||||
<CloudUploadOutline/>
|
||||
</n-icon>
|
||||
</div>
|
||||
<n-text style="font-size: 16px">点击或拖拽文件到此处上传</n-text>
|
||||
<n-p depth="3" style="margin: 8px 0 0 0">支持 .xlsx 或 .xls 格式</n-p>
|
||||
</n-upload-dragger>
|
||||
</n-upload>
|
||||
</n-space>
|
||||
<template #footer>
|
||||
<n-button @click="importModalVisible = false">关闭</n-button>
|
||||
</template>
|
||||
</n-modal>
|
||||
|
||||
|
||||
<n-modal v-model:show="confirmVisible" preset="card" title="确认入库" style="width: 480px">
|
||||
<n-form label-placement="left" label-width="120px">
|
||||
<n-form-item label="入库单号">
|
||||
<n-input :value="confirmRow?.inboundCode" disabled/>
|
||||
</n-form-item>
|
||||
<!-- <n-form-item label="金蝶入库单编码">-->
|
||||
<!-- <n-input v-model:value="confirmKingdeeNo" placeholder="推送金蝶成功后的单号(可后补)" clearable />-->
|
||||
<!-- </n-form-item>-->
|
||||
</n-form>
|
||||
<template #footer>
|
||||
<n-space justify="end">
|
||||
<n-button @click="confirmVisible = false">取消</n-button>
|
||||
<n-button type="primary" :loading="submitLoading" @click="doConfirm">确认入库</n-button>
|
||||
</n-space>
|
||||
</template>
|
||||
</n-modal>
|
||||
|
||||
<!-- 详情 -->
|
||||
<n-modal v-model:show="detailVisible" preset="card" title="入库单详情" style="width: 720px">
|
||||
<n-descriptions v-if="detailData" :column="2" bordered size="small" label-placement="left">
|
||||
<n-descriptions-item label="入库单号">{{ detailData.inboundCode || '-' }}</n-descriptions-item>
|
||||
<n-descriptions-item label="当前阶段">{{ statusLabel(detailData.status) }}</n-descriptions-item>
|
||||
<n-descriptions-item label="入库类型">{{ typeLabel(detailData.inboundType) }}</n-descriptions-item>
|
||||
<n-descriptions-item label="来源单号">{{ detailData.sourceOrderId || '-' }}</n-descriptions-item>
|
||||
<n-descriptions-item label="金蝶入库单编码">{{ detailData.kingdeeInboundNo || '-' }}</n-descriptions-item>
|
||||
<!-- <n-descriptions-item label="物料编码">{{ detailData.materialCode || '-' }}</n-descriptions-item>-->
|
||||
<!-- <n-descriptions-item label="物料名称">{{ detailData.materialName || '-' }}</n-descriptions-item>-->
|
||||
<n-descriptions-item label="入库数量">{{ formatQty(detailData.num) }}</n-descriptions-item>
|
||||
<!-- <n-descriptions-item label="入库仓库">{{ detailData.warehouseName || '-' }}</n-descriptions-item>-->
|
||||
<!-- <n-descriptions-item label="入库进度">{{ detailData.progress ?? 0 }}%</n-descriptions-item>-->
|
||||
<!-- <n-descriptions-item label="创建时间">{{ detailData.createTime || '-' }}</n-descriptions-item>-->
|
||||
</n-descriptions>
|
||||
</n-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {ref, reactive, h, onMounted} from 'vue'
|
||||
import {
|
||||
NButton, NSpace, NIcon, NUpload, useMessage, useDialog, type DataTableColumns, type UploadCustomRequestOptions,
|
||||
NTag, NInput, NForm, NModal, NFormItem, NDescriptionsItem, NDescriptions, NFormItemGi, NInputNumber
|
||||
} from 'naive-ui'
|
||||
import {
|
||||
SearchOutline,
|
||||
RefreshOutline,
|
||||
AddOutline,
|
||||
TrashOutline,
|
||||
CreateOutline,
|
||||
CloudUploadOutline,
|
||||
DownloadOutline
|
||||
} from '@vicons/ionicons5'
|
||||
import {STOCK_IN_STATUS_MAP, STOCK_IN_TYPE_MAP,defectiveWarehouseApi, type DefectiveWarehouse} from '@/api/defectiveWarehouse'
|
||||
import {dictDataApi} from '@/api/org'
|
||||
import { type StockIn, stockInApi} from "@/api/stockIn.ts";
|
||||
|
||||
const message = useMessage()
|
||||
const dialog = useDialog()
|
||||
|
||||
// 搜索表单
|
||||
const searchForm = reactive({
|
||||
id: null as number | null,
|
||||
status: null as number | null,
|
||||
})
|
||||
|
||||
// 表格数据
|
||||
const tableData = ref<DefectiveWarehouse[]>([])
|
||||
const loading = ref(false)
|
||||
const selectedIds = ref<number[]>([])
|
||||
const pagination = reactive({
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
itemCount: 0,
|
||||
showSizePicker: true,
|
||||
pageSizes: [10, 20, 50]
|
||||
})
|
||||
|
||||
// 弹窗
|
||||
const detailVisible = ref(false)
|
||||
const modalVisible = ref(false)
|
||||
const modalTitle = ref('')
|
||||
const importModalVisible = ref(false)
|
||||
const formRef = ref()
|
||||
|
||||
const detailData = ref<DefectiveWarehouse>({})
|
||||
const defaultFormData: DefectiveWarehouse = {
|
||||
processId: undefined,
|
||||
sourceOrderId: undefined,
|
||||
inboundCode: '',
|
||||
subjectName: '',
|
||||
inboundType: undefined,
|
||||
processPlanId: undefined,
|
||||
warehouseId: undefined,
|
||||
status: undefined,
|
||||
businessType: '',
|
||||
}
|
||||
const formData = reactive<DefectiveWarehouse>({...defaultFormData})
|
||||
|
||||
// 字典选项(下拉框/单选框/复选框关联字典时使用)
|
||||
const statusOptions = ref<{ label: string; value: any; class: any }[]>([])
|
||||
|
||||
// 表单校验规则
|
||||
const formRules = {}
|
||||
|
||||
// 表格列
|
||||
const columns: DataTableColumns<DefectiveWarehouse> = [
|
||||
{type: 'selection'},
|
||||
{title: '入库单号', key: 'inboundCode'},
|
||||
{
|
||||
title: '入库类型', key: 'inboundType',
|
||||
render(row) {
|
||||
const item = STOCK_IN_TYPE_MAP[row.inboundType ?? 1] ?? STOCK_IN_TYPE_MAP[1]
|
||||
return h(NTag, {type: item.type, size: 'small', round: true}, {default: () => item.label})
|
||||
}
|
||||
},
|
||||
{title: '入库数量', key: 'num'},
|
||||
{title: '主体名称', key: 'subjectName'},
|
||||
{
|
||||
title: '状态', key: 'status',
|
||||
render(row) {
|
||||
const val = row.status
|
||||
const opt = statusOptions.value.find(o => o.value === val || String(o.value) === String(val))
|
||||
return h(NTag, {type: opt.class, size: 'small'}, {default: () => opt.label})
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'actions',
|
||||
width: 140,
|
||||
fixed: 'right',
|
||||
render(row) {
|
||||
var status = row.status
|
||||
if (status == 0 || status == 1) {
|
||||
return h('div', {style: {display: 'flex', alignItems: 'center', gap: '8px', flexWrap: 'nowrap'}}, [
|
||||
h(NButton, {size: 'small', quaternary: true, onClick: () => handleDetail(row)}, {
|
||||
default: () => ['详情']
|
||||
}),
|
||||
h(NButton, {size: 'small', quaternary: true, onClick: () => handleConfirm(row)}, {
|
||||
default: () => [h(NIcon, null, {default: () => h(CreateOutline)}), '确认入库']
|
||||
}),
|
||||
h(NButton, {size: 'small', quaternary: true, onClick: () => handleEdit(row)}, {
|
||||
default: () => [h(NIcon, null, {default: () => h(CreateOutline)}), ' 编辑']
|
||||
}),
|
||||
h(NButton, {size: 'small', quaternary: true, type: 'error', onClick: () => handleDelete(row)}, {
|
||||
default: () => [h(NIcon, null, {default: () => h(TrashOutline)}), ' 删除']
|
||||
})
|
||||
])
|
||||
} else if (status == 2) {
|
||||
return h('div', {style: {display: 'flex', alignItems: 'center', gap: '8px', flexWrap: 'nowrap'}}, [
|
||||
h(NButton, {size: 'small', quaternary: true, onClick: () => handleDetail(row)}, {
|
||||
default: () => ['详情']
|
||||
}),
|
||||
h(NButton, {size: 'small', quaternary: true, onClick: () => handleCancel(row)}, {
|
||||
default: () => [h(NIcon, null, {default: () => h(CreateOutline)}), '撤回入库']
|
||||
})
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
// 加载数据
|
||||
async function loadData() {
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await defectiveWarehouseApi.page({
|
||||
page: pagination.page,
|
||||
pageSize: pagination.pageSize,
|
||||
id: searchForm.id || undefined,
|
||||
status: searchForm.status || undefined,
|
||||
})
|
||||
tableData.value = res.list
|
||||
pagination.itemCount = res.total
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 搜索
|
||||
function handleSearch() {
|
||||
pagination.page = 1
|
||||
loadData()
|
||||
}
|
||||
|
||||
// 重置
|
||||
function handleReset() {
|
||||
searchForm.id = null
|
||||
|
||||
searchForm.status = null
|
||||
|
||||
handleSearch()
|
||||
}
|
||||
|
||||
// 分页
|
||||
function handlePageChange(page: number) {
|
||||
pagination.page = page
|
||||
loadData()
|
||||
}
|
||||
|
||||
function handlePageSizeChange(pageSize: number) {
|
||||
pagination.pageSize = pageSize
|
||||
pagination.page = 1
|
||||
loadData()
|
||||
}
|
||||
|
||||
// 选择
|
||||
function handleCheck(keys: Array<string | number>) {
|
||||
selectedIds.value = keys as number[]
|
||||
}
|
||||
|
||||
// 新增
|
||||
function handleAdd() {
|
||||
modalTitle.value = '新增不良品库'
|
||||
Object.assign(formData, defaultFormData)
|
||||
modalVisible.value = true
|
||||
}
|
||||
|
||||
// 编辑
|
||||
function handleEdit(row: DefectiveWarehouse) {
|
||||
modalTitle.value = '编辑不良品库'
|
||||
console.log(row)
|
||||
Object.assign(formData, row)
|
||||
modalVisible.value = true
|
||||
}
|
||||
|
||||
// 提交
|
||||
async function handleSubmit() {
|
||||
await formRef.value?.validate()
|
||||
try {
|
||||
const submitData = {...formData} as DefectiveWarehouse
|
||||
if (submitData.id) {
|
||||
await defectiveWarehouseApi.update(submitData)
|
||||
message.success('修改成功')
|
||||
} else {
|
||||
await defectiveWarehouseApi.create(submitData)
|
||||
message.success('新增成功')
|
||||
}
|
||||
modalVisible.value = false
|
||||
loadData()
|
||||
} catch (error) {
|
||||
// 错误已在拦截器处理
|
||||
}
|
||||
}
|
||||
|
||||
// 删除
|
||||
function handleDelete(row: DefectiveWarehouse) {
|
||||
dialog.warning({
|
||||
title: '提示',
|
||||
content: '确定要删除该记录吗?',
|
||||
positiveText: '确定',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: async () => {
|
||||
try {
|
||||
await defectiveWarehouseApi.delete([row.id!])
|
||||
message.success('删除成功')
|
||||
loadData()
|
||||
} catch (error) {
|
||||
// 错误已在拦截器处理
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 批量删除
|
||||
function handleBatchDelete() {
|
||||
dialog.warning({
|
||||
title: '提示',
|
||||
content: `确定要删除选中的 ${selectedIds.value.length} 条记录吗?`,
|
||||
positiveText: '确定',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: async () => {
|
||||
try {
|
||||
await defectiveWarehouseApi.delete(selectedIds.value)
|
||||
message.success('删除成功')
|
||||
selectedIds.value = []
|
||||
loadData()
|
||||
} catch (error) {
|
||||
// 错误已在拦截器处理
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 导出
|
||||
async function handleExport() {
|
||||
try {
|
||||
const params: Record<string, any> = {}
|
||||
if (selectedIds.value.length > 0) params.ids = selectedIds.value
|
||||
if (searchForm.id != null) params.id = searchForm.id
|
||||
if (searchForm.status != null) params.status = searchForm.status
|
||||
const blob = await defectiveWarehouseApi.export(params)
|
||||
const url = window.URL.createObjectURL(blob)
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.download = '不良品库数据.xlsx'
|
||||
link.click()
|
||||
window.URL.revokeObjectURL(url)
|
||||
} catch (error) {
|
||||
// 错误已在拦截器处理
|
||||
}
|
||||
}
|
||||
|
||||
// 下载导入模板
|
||||
async function handleDownloadTemplate() {
|
||||
try {
|
||||
const blob = await defectiveWarehouseApi.downloadTemplate()
|
||||
const url = window.URL.createObjectURL(blob)
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.download = '不良品库导入模板.xlsx'
|
||||
link.click()
|
||||
window.URL.revokeObjectURL(url)
|
||||
} catch (error) {
|
||||
// 错误已在拦截器处理
|
||||
}
|
||||
}
|
||||
|
||||
// 导入上传
|
||||
async function handleImportUpload({file}: UploadCustomRequestOptions) {
|
||||
if (!file.file) return
|
||||
try {
|
||||
const result = await defectiveWarehouseApi.importData(file.file)
|
||||
if (result.fail > 0) {
|
||||
dialog.warning({
|
||||
title: '导入结果',
|
||||
content: `成功: ${result.success} 条,失败: ${result.fail} 条\n错误信息: ${(result.errors || []).join('\n') || '无'}`,
|
||||
positiveText: '确定'
|
||||
})
|
||||
} else {
|
||||
message.success(`导入成功,共 ${result.success} 条数据`)
|
||||
importModalVisible.value = false
|
||||
}
|
||||
loadData()
|
||||
} catch (error) {
|
||||
// 错误已在拦截器处理
|
||||
}
|
||||
}
|
||||
|
||||
const confirmVisible = ref(false)
|
||||
const confirmRow = ref<StockIn | null>(null)
|
||||
|
||||
//确认入库
|
||||
const handleConfirm = async (row: any) => {
|
||||
confirmVisible.value = true
|
||||
confirmRow.value = row
|
||||
|
||||
}
|
||||
|
||||
|
||||
const doConfirm = async () => {
|
||||
try {
|
||||
await defectiveWarehouseApi.confirm(confirmRow.value.id)
|
||||
message.success("入库成功")
|
||||
loadData()
|
||||
} catch (error) {
|
||||
console.log("确认入库异常" + error)
|
||||
message.error("确认入库异常")
|
||||
} finally {
|
||||
confirmVisible.value = false
|
||||
}
|
||||
}
|
||||
|
||||
//撤回入库
|
||||
const handleCancel = async (row: any) => {
|
||||
dialog.warning({
|
||||
title: '撤回入库',
|
||||
content: `确认撤回入库单 ${row.inboundCode}?`,
|
||||
positiveText: '撤回',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: async () => {
|
||||
try {
|
||||
await defectiveWarehouseApi.cancel(row.id!)
|
||||
message.success('已撤回')
|
||||
loadData()
|
||||
} catch (e: any) {
|
||||
message.error(e?.message || '撤回失败')
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
//详情
|
||||
const handleDetail = (row:any)=>{
|
||||
detailVisible.value = true
|
||||
detailData.value = row
|
||||
}
|
||||
|
||||
|
||||
function statusLabel(status?: number) {
|
||||
if (status == null) return '-'
|
||||
return STOCK_IN_STATUS_MAP[status]?.label ?? String(status)
|
||||
}
|
||||
|
||||
function typeLabel(type?: number) {
|
||||
if (type == null) return '-'
|
||||
return STOCK_IN_TYPE_MAP[type]?.label ?? String(type)
|
||||
}
|
||||
|
||||
function formatQty(val?: number | string | null) {
|
||||
if (val == null || val === '') return '0'
|
||||
return Number(val).toLocaleString()
|
||||
}
|
||||
|
||||
const typeOptions = Object.entries(STOCK_IN_TYPE_MAP).map(([value, item]) => ({
|
||||
label: item.label,
|
||||
value: Number(value),
|
||||
}))
|
||||
|
||||
// 加载字典选项
|
||||
async function loadDictOptions() {
|
||||
try {
|
||||
const data = await dictDataApi.listByType('defetive_status')
|
||||
statusOptions.value = data.map(d => ({label: d.dictLabel, value: (Number(d.dictValue) || d.dictValue)}))
|
||||
} catch {
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadData()
|
||||
loadDictOptions()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.search-form {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.table-toolbar {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
</style>
|
||||
@ -37,6 +37,8 @@ const columns = [
|
||||
key: 'quantity',
|
||||
width: 120
|
||||
},
|
||||
{ title: '合格数量', key: 'qualifiedQty',align: 'center', width: 120},
|
||||
{ title: '报废数量', key: 'scrapeQty',align: 'center', width: 120},
|
||||
{
|
||||
title: '提交人',
|
||||
key: 'userName',
|
||||
|
||||
@ -12,6 +12,8 @@ const searchForm = ref({
|
||||
submitStatus: undefined
|
||||
})
|
||||
|
||||
const reportTypeOptions = ref<{ label: string; value: any ;class:any}[]>([])
|
||||
|
||||
const submitList = ref<SubmitLog[]>([])
|
||||
//根据工序Id加载汇报详情
|
||||
async function loadReportDetail() {
|
||||
@ -33,28 +35,11 @@ const columns = [
|
||||
{
|
||||
title: '提交数量',
|
||||
key: 'quantity',
|
||||
align: 'center',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '完成数量',
|
||||
key: 'qualifiedQty',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '报废数量',
|
||||
key: 'scrapQty',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '返工数量',
|
||||
key: 'reworkQty',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '让步接收数量',
|
||||
key: 'connectionQty',
|
||||
width: 120
|
||||
},
|
||||
{ title: '合格数量', key: 'qualifiedQty',align: 'center', width: 120},
|
||||
{ title: '报废数量', key: 'scrapeQty',align: 'center', width: 120},
|
||||
{
|
||||
title: '提交人',
|
||||
key: 'userName',
|
||||
@ -84,6 +69,10 @@ async function loadDictOptions() {
|
||||
const data = await dictDataApi.listByType('submit_status')
|
||||
submitStatusOptions.value = data.map(d => ({ label: d.dictLabel, value: (Number(d.dictValue) || d.dictValue),class:d.listClass }))
|
||||
}catch {}
|
||||
try {
|
||||
const data = await dictDataApi.listByType('qc_result_type')
|
||||
reportTypeOptions.value = data.map(d => ({ label: d.dictLabel, value: (Number(d.dictValue) || d.dictValue),class:d.listClass }))
|
||||
}catch {}
|
||||
}
|
||||
|
||||
const doShowInner = () => {
|
||||
|
||||
@ -180,8 +180,8 @@
|
||||
|
||||
|
||||
<!--质检单详情面板-->
|
||||
<n-modal v-model:show="detailVisible" preset="card" :title="detailTitle" style="width: 800px">
|
||||
<n-card hoverable style="margin-bottom: 12px" >
|
||||
<n-drawer v-model:show="detailVisible" preset="card" :title="detailTitle" style="width: 1200px">
|
||||
<n-card hoverable style="margin: 10px" >
|
||||
<template #header>
|
||||
<div style="display:flex;justify-content:space-between;align-items:center;width:100%">
|
||||
<span>主表信息</span>
|
||||
@ -190,7 +190,7 @@
|
||||
</n-button>
|
||||
</div>
|
||||
</template>
|
||||
<n-descriptions :column="3" bordered v-show="!infoIsCollapse">
|
||||
<n-descriptions :column="8" bordered v-show="!infoIsCollapse">
|
||||
<n-descriptions-item
|
||||
v-for="item in mappedInfoList"
|
||||
:key="item.key"
|
||||
@ -200,7 +200,7 @@
|
||||
</n-descriptions-item>
|
||||
</n-descriptions>
|
||||
</n-card>
|
||||
<n-card hoverable style="margin-bottom: 12px">
|
||||
<n-card hoverable style="margin: 10px">
|
||||
<template #header>
|
||||
<div style="display:flex;justify-content:space-between;align-items:center;width:100%">
|
||||
<span>明细列表</span>
|
||||
@ -223,7 +223,7 @@
|
||||
<!-- <n-card title="追溯码" hoverable>-->
|
||||
<!-- 追溯码:{{}}-->
|
||||
<!-- </n-card>-->
|
||||
</n-modal>
|
||||
</n-drawer>
|
||||
|
||||
<!-- 提交判定明细抽屉 -->
|
||||
<n-drawer v-model:show="showSubmitOuter" :width="900">
|
||||
@ -328,7 +328,7 @@ const detailVisible = ref(false)
|
||||
const detailTitle = ref('')
|
||||
|
||||
const infoIsCollapse = ref(false)
|
||||
const detailIsCollapse = ref(true)
|
||||
const detailIsCollapse = ref(false)
|
||||
|
||||
//提交判定明细
|
||||
// const submitDetailModalVisible = ref(false)
|
||||
@ -401,29 +401,13 @@ const detailColumns: DataTableColumns<QcResultDetail> = [
|
||||
{
|
||||
title: '批次号',
|
||||
key: 'traceCode',
|
||||
width: 80,
|
||||
width: 150,
|
||||
align: 'center',
|
||||
render: (row) => {
|
||||
const val = row.traceCode
|
||||
return val ?? '-'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '不良代码',
|
||||
key: 'defectCode',
|
||||
width: 80,
|
||||
align: 'center',
|
||||
render: (row) => {
|
||||
const val = row.defectCode
|
||||
return val ?? '-'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '后续动作',
|
||||
key: 'handleAction',
|
||||
width: 80,
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '动作执行状态',
|
||||
key: 'actionStatus',
|
||||
@ -638,8 +622,8 @@ const columns: DataTableColumns<QualityTesting> = [
|
||||
{ label: '提交判定明细', key: 'submitResultDetail',show:row.status == 1 },
|
||||
// { type: 'divider',show:row.status == 1 }, // 分割线
|
||||
// { label: '提交部分判定明细', key: 'submitBFResultDetail',show:(row.status == 1 || row.status == 2) },
|
||||
{ type: 'divider',show:(row.status == 1 || row.status == 2) }, // 分割线
|
||||
{ label: '查询判定明细', key: 'queryResultDetail' },
|
||||
// { type: 'divider',show:(row.status == 1 || row.status == 2) }, // 分割线
|
||||
// { label: '查询判定明细', key: 'queryResultDetail' },
|
||||
// { type: 'divider' }, // 分割线
|
||||
// { label: '质检撤回', key: 'cancelQuality' },
|
||||
],
|
||||
|
||||
@ -385,7 +385,7 @@ const columns: DataTableColumns<StockIn> = [
|
||||
const btns = [
|
||||
h(NButton, { text: true, type: 'primary', size: 'small', onClick: () => openDetail(row) }, { default: () => '详情' }),
|
||||
]
|
||||
if (status === 0 || status === 1 || status === 3) {
|
||||
if (status === 0 || status === 1) {
|
||||
btns.push(
|
||||
h(NButton, {
|
||||
text: true,
|
||||
|
||||
@ -1050,7 +1050,7 @@ const selectedDeviceIds = ref<Device[]>([])
|
||||
|
||||
function handlerConnectionDevice(row:any) {
|
||||
deviceDocumentConnectionVisible.value = true
|
||||
title.value = row.deviceName + "图文工艺文档关联"
|
||||
title.value = row.drawingName + "关联设备"
|
||||
deviceDocumentConnection.sourceId = row.id
|
||||
getDeviceList(deviceDocumentConnection.sourceId)
|
||||
}
|
||||
|
||||
@ -207,29 +207,13 @@ const detailColumns: DataTableColumns<QcResultDetail> = [
|
||||
{
|
||||
title: '批次号',
|
||||
key: 'traceCode',
|
||||
width: 80,
|
||||
width: 120,
|
||||
align: 'center',
|
||||
render: (row) => {
|
||||
const val = row.traceCode
|
||||
return val ?? '-'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '不良代码',
|
||||
key: 'defectCode',
|
||||
width: 80,
|
||||
align: 'center',
|
||||
render: (row) => {
|
||||
const val = row.defectCode
|
||||
return val ?? '-'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '后续动作',
|
||||
key: 'handleAction',
|
||||
width: 80,
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
key: 'actionStatus',
|
||||
|
||||
@ -65,7 +65,7 @@ const props =defineProps(
|
||||
|
||||
//汇报状态字典
|
||||
const submitStatusOptions = ref<{ label: string; value: any ;class:any}[]>([])
|
||||
|
||||
const reportTypeOptions = ref<{ label: string; value: any ;class:any}[]>([])
|
||||
|
||||
const pagination = reactive({
|
||||
page: 1,
|
||||
@ -75,10 +75,9 @@ const pagination = reactive({
|
||||
|
||||
//汇报信息表格
|
||||
const reportRecordsColums:DataTableColumns<SubmitLog> = [
|
||||
|
||||
{ title: '汇报数量', key: 'quantity',align: 'center'},
|
||||
{ title: '合格数量', key: 'qualifiedQty',align: 'center'},
|
||||
{ title: '报废数量', key: 'scrapQty',align: 'center'},
|
||||
{ title: '报废数量', key: 'scrapeQty',align: 'center'},
|
||||
{ title: '汇报人', key: 'userName',align: 'center' },
|
||||
{ title: '状态', key: 'submitStatus',align: 'center',
|
||||
render: (row) => {
|
||||
@ -98,6 +97,10 @@ async function loadDictOptions() {
|
||||
const data = await dictDataApi.listByType('submit_status')
|
||||
submitStatusOptions.value = data.map(d => ({ label: d.dictLabel, value: (Number(d.dictValue) || d.dictValue),class:d.listClass }))
|
||||
}catch {}
|
||||
try {
|
||||
const data = await dictDataApi.listByType('qc_result_type')
|
||||
reportTypeOptions.value = data.map(d => ({ label: d.dictLabel, value: (Number(d.dictValue) || d.dictValue),class:d.listClass }))
|
||||
}catch {}
|
||||
}
|
||||
|
||||
//加载汇报信息
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
label-placement="left"
|
||||
>
|
||||
<n-grid :cols="24" :x-gap="24">
|
||||
<n-form-item-gi :span="4" label="派工编号">
|
||||
<n-form-item-gi :span="4" label="派工编号">
|
||||
<n-input v-model:value="searchForm.assingCode" placeholder="请输入派工编号" clearable />
|
||||
</n-form-item-gi>
|
||||
<n-form-item-gi :span="4" label="物料编码">
|
||||
@ -21,6 +21,9 @@
|
||||
<n-form-item-gi :span="4" label="工序名称">
|
||||
<n-input v-model:value="searchForm.processName" placeholder="请输入工序名称" clearable />
|
||||
</n-form-item-gi>
|
||||
<n-form-item-gi :span="4" label="工单号">
|
||||
<n-input v-model:value="searchForm.workOrderCode" placeholder="请输入工单号" clearable />
|
||||
</n-form-item-gi>
|
||||
<n-form-item-gi :span="4">
|
||||
<n-space>
|
||||
<n-button type="primary" @click="search">
|
||||
@ -268,6 +271,7 @@ const searchForm = reactive({
|
||||
assingCode:'',
|
||||
materialCode:'',
|
||||
materialName:'',
|
||||
workOrderCode:''
|
||||
})
|
||||
|
||||
|
||||
@ -499,6 +503,7 @@ function search() {
|
||||
assingCode: searchForm.assingCode,
|
||||
materialCode: searchForm.materialCode,
|
||||
materialName: searchForm.materialName,
|
||||
workOrderCode:searchForm.workOrderCode
|
||||
})
|
||||
}
|
||||
|
||||
@ -509,6 +514,7 @@ function reset() {
|
||||
searchForm.assingCode = ''
|
||||
searchForm.materialCode = ''
|
||||
searchForm.materialName = ''
|
||||
searchForm.workOrderCode = ''
|
||||
treeTableRef.value?.loadTableData({})
|
||||
}
|
||||
|
||||
@ -519,6 +525,7 @@ function getlist() {
|
||||
assingCode: searchForm.assingCode,
|
||||
materialCode: searchForm.materialCode,
|
||||
materialName: searchForm.materialName,
|
||||
workOrderCode: searchForm.workOrderCode
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user