提交代码
This commit is contained in:
parent
69f49d436a
commit
383591d02f
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"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
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: () => 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)}), ' 删除']
|
||||||
|
}),
|
||||||
|
h(NButton, {size: 'small', quaternary: true, onClick: () => handleDetail(row)}, {
|
||||||
|
default: () => ['详情']
|
||||||
|
})
|
||||||
|
])
|
||||||
|
} else if (status == 2) {
|
||||||
|
return h('div', {style: {display: 'flex', alignItems: 'center', gap: '8px', flexWrap: 'nowrap'}}, [
|
||||||
|
h(NButton, {size: 'small', quaternary: true, onClick: () => handleCancel(row)}, {
|
||||||
|
default: () => [h(NIcon, null, {default: () => h(CreateOutline)}), '撤回入库']
|
||||||
|
}),
|
||||||
|
h(NButton, {size: 'small', quaternary: true, onClick: () => handleDetail(row)}, {
|
||||||
|
default: () => ['详情']
|
||||||
|
})
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
// 加载数据
|
||||||
|
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',
|
key: 'quantity',
|
||||||
width: 120
|
width: 120
|
||||||
},
|
},
|
||||||
|
{ title: '合格数量', key: 'qualifiedQty',align: 'center', width: 120},
|
||||||
|
{ title: '报废数量', key: 'scrapQty',align: 'center', width: 120},
|
||||||
{
|
{
|
||||||
title: '提交人',
|
title: '提交人',
|
||||||
key: 'userName',
|
key: 'userName',
|
||||||
|
|||||||
@ -12,6 +12,8 @@ const searchForm = ref({
|
|||||||
submitStatus: undefined
|
submitStatus: undefined
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const reportTypeOptions = ref<{ label: string; value: any ;class:any}[]>([])
|
||||||
|
|
||||||
const submitList = ref<SubmitLog[]>([])
|
const submitList = ref<SubmitLog[]>([])
|
||||||
//根据工序Id加载汇报详情
|
//根据工序Id加载汇报详情
|
||||||
async function loadReportDetail() {
|
async function loadReportDetail() {
|
||||||
@ -33,28 +35,11 @@ const columns = [
|
|||||||
{
|
{
|
||||||
title: '提交数量',
|
title: '提交数量',
|
||||||
key: 'quantity',
|
key: 'quantity',
|
||||||
|
align: 'center',
|
||||||
width: 120
|
width: 120
|
||||||
},
|
},
|
||||||
{
|
{ title: '合格数量', key: 'qualifiedQty',align: 'center', width: 120},
|
||||||
title: '完成数量',
|
{ title: '报废数量', key: 'scrapQty',align: 'center', width: 120},
|
||||||
key: 'qualifiedQty',
|
|
||||||
width: 120
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '报废数量',
|
|
||||||
key: 'scrapQty',
|
|
||||||
width: 120
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '返工数量',
|
|
||||||
key: 'reworkQty',
|
|
||||||
width: 120
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '让步接收数量',
|
|
||||||
key: 'connectionQty',
|
|
||||||
width: 120
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: '提交人',
|
title: '提交人',
|
||||||
key: 'userName',
|
key: 'userName',
|
||||||
@ -84,6 +69,10 @@ async function loadDictOptions() {
|
|||||||
const data = await dictDataApi.listByType('submit_status')
|
const data = await dictDataApi.listByType('submit_status')
|
||||||
submitStatusOptions.value = data.map(d => ({ label: d.dictLabel, value: (Number(d.dictValue) || d.dictValue),class:d.listClass }))
|
submitStatusOptions.value = data.map(d => ({ label: d.dictLabel, value: (Number(d.dictValue) || d.dictValue),class:d.listClass }))
|
||||||
}catch {}
|
}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 = () => {
|
const doShowInner = () => {
|
||||||
|
|||||||
@ -385,7 +385,7 @@ const columns: DataTableColumns<StockIn> = [
|
|||||||
const btns = [
|
const btns = [
|
||||||
h(NButton, { text: true, type: 'primary', size: 'small', onClick: () => openDetail(row) }, { default: () => '详情' }),
|
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(
|
btns.push(
|
||||||
h(NButton, {
|
h(NButton, {
|
||||||
text: true,
|
text: true,
|
||||||
|
|||||||
@ -65,7 +65,7 @@ const props =defineProps(
|
|||||||
|
|
||||||
//汇报状态字典
|
//汇报状态字典
|
||||||
const submitStatusOptions = ref<{ label: string; value: any ;class:any}[]>([])
|
const submitStatusOptions = ref<{ label: string; value: any ;class:any}[]>([])
|
||||||
|
const reportTypeOptions = ref<{ label: string; value: any ;class:any}[]>([])
|
||||||
|
|
||||||
const pagination = reactive({
|
const pagination = reactive({
|
||||||
page: 1,
|
page: 1,
|
||||||
@ -75,10 +75,9 @@ const pagination = reactive({
|
|||||||
|
|
||||||
//汇报信息表格
|
//汇报信息表格
|
||||||
const reportRecordsColums:DataTableColumns<SubmitLog> = [
|
const reportRecordsColums:DataTableColumns<SubmitLog> = [
|
||||||
|
|
||||||
{ title: '汇报数量', key: 'quantity',align: 'center'},
|
{ title: '汇报数量', key: 'quantity',align: 'center'},
|
||||||
{ title: '合格数量', key: 'qualifiedQty',align: 'center'},
|
{ title: '合格数量', key: 'qualifiedQty',align: 'center'},
|
||||||
{ title: '报废数量', key: 'scrapQty',align: 'center'},
|
{ title: '报废数量', key: 'scrapeQty',align: 'center'},
|
||||||
{ title: '汇报人', key: 'userName',align: 'center' },
|
{ title: '汇报人', key: 'userName',align: 'center' },
|
||||||
{ title: '状态', key: 'submitStatus',align: 'center',
|
{ title: '状态', key: 'submitStatus',align: 'center',
|
||||||
render: (row) => {
|
render: (row) => {
|
||||||
@ -98,6 +97,10 @@ async function loadDictOptions() {
|
|||||||
const data = await dictDataApi.listByType('submit_status')
|
const data = await dictDataApi.listByType('submit_status')
|
||||||
submitStatusOptions.value = data.map(d => ({ label: d.dictLabel, value: (Number(d.dictValue) || d.dictValue),class:d.listClass }))
|
submitStatusOptions.value = data.map(d => ({ label: d.dictLabel, value: (Number(d.dictValue) || d.dictValue),class:d.listClass }))
|
||||||
}catch {}
|
}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 {}
|
||||||
}
|
}
|
||||||
|
|
||||||
//加载汇报信息
|
//加载汇报信息
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user