调整预生产接口

This commit is contained in:
andy 2026-06-09 10:30:07 +08:00
parent 57c7eb92eb
commit 11ce22d245
5 changed files with 730 additions and 211 deletions

View File

@ -52,6 +52,48 @@ export interface OrderItem {
proWorkshop?: string
}
export interface KingdeePrdMo {
productionOrderNo: string
billNo: string
workShopName: string
materialCode: string
quantity: number | null
specModel: string | null
unit: string | null
materialName: string | null
routingNo: string | null
planStartTime: string | null
planFinishTime: string | null
pickMtrlStatus: string | null
children: KingdeeProcessRoute[]
}
/** 金蝶工艺路线工序(树子节点) */
export interface KingdeeProcessRoute {
/** 工序号 FOperNumber */
operNumber: number | null
/** 工作中心 FWorkCenterId.FName */
workCenterName: string | null
/** 生产车间 FDepartmentId.FName */
departmentName: string | null
/** 工序名称 FProcessProperty */
processName: string | null
/** 工序说明 FOperDescription */
operDescription: string | null
/** 活动单位 FActivity1UnitID.FName */
activityUnit: string | null
/** 工序控制码 FOptCtrlCodeId.FName */
optCtrlCodeName: string | null
/** 活动量 FActivity1Qty */
activityQty: number | null
/** 计划开始时间 yyyy-MM-dd HH:mm:ss */
planStartTime: string | null
/** 计划结束时间 yyyy-MM-dd HH:mm:ss */
planFinishTime: string | null
}
// 生产订单 API
export const orderItemApi = {
// 分页查询
@ -86,6 +128,11 @@ export const orderItemApi = {
preCreation(data: any) {
return request({ url: '/biz/orderItem/preCreation', method: 'post', data })
},
//根据生产编号查询预生产订单
preCreationInfo(id: number, params:any) {
debugger;
return request({ url: `/biz/orderItem/preCreation/${id}`, method: 'get', params})
},
//查询项目名称
xmoptions(params: any) {
@ -96,6 +143,10 @@ export const orderItemApi = {
wloptions(params: any) { //projectId
return request({ url: '/biz/orderItem/options', method: 'get', params })
},
holdTemporarilySave(id: number, data: KingdeePrdMo[]){
return request({ url: `/biz/orderItem/kingdee/temporarily/save/${id}`, method: 'post', data })
},
// 导出
export(params?: {

View File

@ -175,8 +175,8 @@ export const orderProjectApi = {
},
// 查询金蝶生产订单 (支持优先读取本地暂存)
getKingdeeOrder(id: number) {
return request<KingdeePrdMo[]>({ url: `/biz/orderProject/kingdee/order/${id}`, method: 'get' })
getKingdeeOrder(id: number, params:any) {
return request<KingdeePrdMo[]>({ url: `/biz/orderProject/kingdee/order/${id}`, method: 'get', params })
},
// 暂存金蝶生产订单数据(草稿)

View File

@ -0,0 +1,458 @@
<template>
<div class="kingdee-toolbar">
<n-space>
<n-button
size="small"
:disabled="kingdeeLoading || !kingdeeTableData.length"
@click="kingdeeToggleExpandAll"
>
{{ kingdeeAllExpanded ? '全部收起' : '全部展开' }}
</n-button>
<n-button
size="small"
type="primary"
:disabled="kingdeeLoading || !kingdeeTableData.length"
@click="handleGanttSchedule"
>
<template #icon><n-icon><CalendarOutline /></n-icon></template>
甘特图排产
</n-button>
</n-space>
</div>
<n-data-table
v-model:expanded-row-keys="kingdeeExpandedKeys"
:columns="kingdeeMoColumns"
:data="kingdeeTableData"
:loading="kingdeeLoading"
:row-key="kingdeeMoRowKey"
:scroll-x="kingdeeMoScrollX"
:max-height="kingdeeTableMaxHeight"
:row-class-name="kingdeeMoRowClassName"
size="small"
style="margin-bottom:15px"
/>
<div style="margin-bottom: 1px;">
<!-- <template #footer> -->
<n-space justify="end">
<n-button type="error" :disabled="kingdeeLoading" @click="reCrawlReorderForm">
重新读取数据
</n-button>
<n-button type="primary" :disabled="kingdeeLoading" @click="handleSaveDraft">
保存草稿
</n-button>
<n-button type="info" :disabled="kingdeeLoading" @click="handleSyncOrderAndPlan">
同步订单计划
</n-button>
<n-button @click="$emit('close-modal')">关闭</n-button>
</n-space>
<!-- </template> -->
</div>
</template>
<script setup lang="ts">
import { ref, h, computed, defineProps, onMounted, watch, defineEmits} from 'vue'
import { NButton, NSpace, NIcon, NTag, NDatePicker, NDataTable, useMessage, useDialog, type DataTableColumns } from 'naive-ui'
import { type KingdeePrdMo, type KingdeeProcessRoute } from '@/api/orderProject'
import { useRouter } from 'vue-router'
import { CalendarOutline } from '@vicons/ionicons5'
const emit = defineEmits(['holdTemporarilyCallback', "synchronizationCallback","reCrawlCallback"])
const dialog = useDialog()
const message = useMessage()
const router = useRouter()
const props = defineProps({
kingdeeTableData: {
type: Array,
default: () => []
},
selectedId:{
type: Number,
default: null
}
})
onMounted(() => {
kingdeeTableData.value = props.kingdeeTableData as KingdeeMoTableRow[]
})
watch(()=>props.kingdeeTableData,()=>{
kingdeeTableData.value = props.kingdeeTableData as KingdeeMoTableRow[]
},{ deep: true } )
const kingdeeModalVisible = ref(false)
const kingdeeLoading = ref(false)
/** 主表行:工序仅存 processRoutes避免 children 触发树形重复行 */
type KingdeeMoTableRow = Omit<KingdeePrdMo, 'children'> & { processRoutes: KingdeeProcessRoute[] }
const kingdeeTableData = ref<KingdeeMoTableRow[]>([])
const kingdeeExpandedKeys = ref<Array<string | number>>([])
// const kingdeeCurrentProjectId = ref<number | null>(null) // ID
const kingdeeTableMaxHeight = 'min(78vh, 720px)'
const kingdeeMoScrollX = 1820
const kingdeeProcessScrollX = 1360
const kingdeeMoColumns: DataTableColumns<KingdeeMoTableRow> = [
{
type: 'expand',
expandable: () => true,
renderExpand: (row) => renderKingdeeExpand(row),
},
{
title: '类型', key: 'rowType', width: 96, align: 'center',
render() {
return h(NTag, { size: 'small', type: 'info', bordered: false }, { default: () => '生产订单' })
}
},
{ title: '单据编号', key: 'billNo', width: 120, align: 'center', ellipsis: { tooltip: true } },
{ title: '生产令号', key: 'productionOrderNo', width: 130, align: 'center', ellipsis: { tooltip: true } },
{ title: '工艺路线', key: 'routingNo', width: 110, align: 'center', ellipsis: { tooltip: true } },
{ title: '物料编码', key: 'materialCode', width: 180, ellipsis: { tooltip: true } },
{ title: '物料名称', key: 'materialName', width: 160, ellipsis: { tooltip: true } },
{
title: '数量', key: 'quantity', width: 90, align: 'center',
render(row) {
return formatKingdeeQty(row.quantity)
}
},
{ title: '生产车间', key: 'workShopName', width: 100, align: 'center', ellipsis: { tooltip: true } },
{ title: '规格型号', key: 'specModel', width: 110, align: 'center', ellipsis: { tooltip: true } },
{ title: '单位', key: 'unit', width: 60, align: 'center' },
{
title: '计划开工', key: 'planStartTime', width: 180, align: 'center',
render(row) {
return renderKingdeePlanPickerMo(row, 'planStartTime')
}
},
{
title: '计划完工', key: 'planFinishTime', width: 180, align: 'center',
render(row) {
return renderKingdeePlanPickerMo(row, 'planFinishTime')
}
},
{
title: '领料状态', key: 'pickMtrlStatus', width: 90, align: 'center',
render(row) {
const val = row.pickMtrlStatus
return val != null ? (pickMtrlStatusMap[String(val)] ?? val) : '-'
}
},
]
const kingdeeProcessColumns: DataTableColumns<KingdeeProcessRoute> = [
{
title: '类型', key: 'rowType', width: 72, align: 'center',
render() {
return h(NTag, { size: 'small', type: 'warning', bordered: false }, { default: () => '工序' })
}
},
{
title: '工序号', key: 'operNumber', width: 80, align: 'center',
render(row) {
return row.operNumber != null ? String(row.operNumber) : '-'
}
},
{ title: '工序名称', key: 'processProperty', width: 100, align: 'center' },
{ title: '工序说明', key: 'operDescription', width: 140, ellipsis: { tooltip: true } },
{ title: '工作中心', key: 'workCenterName', width: 110, align: 'center', ellipsis: { tooltip: true } },
{ title: '生产车间', key: 'departmentName', width: 110, align: 'center', ellipsis: { tooltip: true } },
{
title: '计划开始时间', key: 'planStartTime', width: 180, align: 'center',
render(row) {
return renderKingdeePlanPicker(row, 'planStartTime')
}
},
{
title: '计划结束时间', key: 'planFinishTime', width: 180, align: 'center',
render(row) {
return renderKingdeePlanPicker(row, 'planFinishTime')
}
},
{
title: '活动量', key: 'activityQty', width: 90, align: 'center',
render(row) {
return formatKingdeeQty(row.activityQty)
}
},
{ title: '活动单位', key: 'activityUnit', width: 80, align: 'center' },
{ title: '控制码', key: 'optCtrlCodeName', width: 120, align: 'center', ellipsis: { tooltip: true } },
]
const kingdeeAllExpanded = computed(() => {
const total = kingdeeTableData.value.length
if (!total) return false
return kingdeeExpandedKeys.value.length >= total
})
const pickMtrlStatusMap: Record<string, string> = {
'1': '未领料',
'2': '待定',
'3': '已领料',
}
function kingdeeMoRowClassName() {
return 'kingdee-mo-row'
}
function formatDateTime(ts: number) {
const d = new Date(ts)
const pad = (n: number) => String(n).padStart(2, '0')
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`
}
function parseKingdeePlanTime(val: string | number | null | undefined): number | null {
if (val == null || val === '') return null
if (typeof val === 'number') return val
const ts = new Date(val.replace(' ', 'T')).getTime()
return Number.isNaN(ts) ? null : ts
}
function renderKingdeePlanPicker(row: KingdeeProcessRoute, field: 'planStartTime' | 'planFinishTime') {
return h(NDatePicker, {
value: parseKingdeePlanTime(row[field]),
type: 'datetime',
clearable: true,
size: 'small',
style: { width: '100%' },
onUpdateValue: (val: number | null) => {
row[field] = val != null ? formatDateTime(val) : null
},
})
}
function renderKingdeePlanPickerMo(row: KingdeeMoTableRow, field: 'planStartTime' | 'planFinishTime') {
return h(NDatePicker, {
value: parseKingdeePlanTime(row[field]),
type: 'datetime',
clearable: true,
size: 'small',
style: { width: '100%' },
onUpdateValue: (val: number | null) => {
row[field] = val != null ? formatDateTime(val) : null
},
})
}
function formatKingdeeQty(val: number | null | undefined) {
return val != null ? Number(val).toFixed(3) : '-'
}
function kingdeeMoRowKey(row: KingdeeMoTableRow) {
return `mo-${row.productionOrderNo}-${row.billNo}`
}
function kingdeeToggleExpandAll() {
if (kingdeeAllExpanded.value) {
kingdeeExpandedKeys.value = []
} else {
kingdeeExpandedKeys.value = kingdeeTableData.value.map(kingdeeMoRowKey)
}
}
function renderKingdeeExpand(row: KingdeeMoTableRow) {
const routes = getKingdeeRoutes(row)
if (!routes.length) {
return h('div', { class: 'kingdee-expand-empty' }, '暂无工艺路线工序')
}
return h('div', { class: 'kingdee-expand-wrap' }, [
h(NDataTable, {
class: 'kingdee-process-table',
columns: kingdeeProcessColumns,
data: routes,
rowKey: kingdeeProcessRowKey,
size: 'small',
bordered: true,
striped: true,
scrollX: kingdeeProcessScrollX,
}),
])
}
function getKingdeeRoutes(mo: KingdeeMoTableRow) {
return mo.processRoutes
}
function kingdeeProcessRowKey(row: KingdeeProcessRoute) {
return `route-${row.operNumber}-${row.workCenterName}-${row.operDescription}`
}
//
function handleGanttSchedule() {
// ID sessionStorage使
sessionStorage.setItem('gantt_schedule_data', JSON.stringify(kingdeeTableData.value))
if (props.selectedId) {
sessionStorage.setItem('gantt_project_id', String(props.selectedId))
}
//
router.push('/biz/orderProject/gantt')
}
//
async function handleSyncOrderAndPlan() {
if (!props.selectedId) return
kingdeeLoading.value = true
try {
// processRoutes children
const draftData = kingdeeTableData.value.map(mo => {
const { processRoutes, ...rest } = mo
return { ...rest, children: processRoutes } as KingdeePrdMo
})
emit('synchronizationCallback', props.selectedId, draftData)
message.success('同步订单计划成功')
kingdeeModalVisible.value = false
} catch (error) {
//
} finally {
kingdeeLoading.value = false
}
}
const reCrawlReorderForm = () => {
// // 稿
if (!props.selectedId) return
dialog.warning({
title: '提示',
content: '重启读取会导致当前页面数据全部重置, 确定需要重新读取吗?',
positiveText: '确定',
negativeText: '取消',
onPositiveClick: () => {
kingdeeLoading.value = true
try {
emit('reCrawlCallback', props.selectedId, true)
message.success('重启读取成功')
} catch (error) {
//
} finally {
kingdeeLoading.value = false
}
}
})
}
const handleSaveDraft = () => {
// // 稿
if (!props.selectedId) return
kingdeeLoading.value = true
try {
const draftData = kingdeeTableData.value.map(mo => {
const { processRoutes, ...rest } = mo
return { ...rest, children: processRoutes } as KingdeePrdMo
})
emit('holdTemporarilyCallback', props.selectedId, draftData)
message.success('草稿保存成功')
} catch (error) {
//
} finally {
kingdeeLoading.value = false
}
}
// // 稿
// async function handleSaveDraft() {
// if (!kingdeeCurrentProjectId) return
// kingdeeLoading.value = true
// try {
// // processRoutes children
// const draftData = kingdeeTableData.value.map(mo => {
// const { processRoutes, ...rest } = mo
// return { ...rest, children: processRoutes } as KingdeePrdMo
// })
// emit('holdTemporarilyCallback', { id:kingdeeCurrentProjectId, data:draftData })
// // await orderProjectApi.saveKingdeeOrderDraft(kingdeeCurrentProjectId.value, draftData)
// // message.success('稿')
// } catch (error) {
// //
// } finally {
// kingdeeLoading.value = false
// }
// }
</script>
<style scoped>
.search-form {
margin-bottom: 16px;
}
.table-toolbar {
margin-bottom: 16px;
}
.kingdee-toolbar {
margin-bottom: 12px;
}
:deep(.kingdee-modal .n-card) {
max-height: 94vh;
display: flex;
flex-direction: column;
}
:deep(.kingdee-modal .n-card__content) {
flex: 1;
min-height: 0;
overflow: hidden;
}
:deep(.kingdee-mo-row td) {
background-color: rgba(32, 128, 240, 0.06) !important;
font-weight: 500;
}
:deep(.kingdee-mo-row:hover td) {
background-color: rgba(32, 128, 240, 0.1) !important;
}
.kingdee-expand-wrap {
margin: 4px 8px 8px 36px;
padding: 12px 14px 14px;
border: 1px solid var(--n-border-color);
border-left: 4px solid #18a058;
border-radius: 6px;
background: var(--n-action-color);
}
:deep(.kingdee-process-table .n-data-table-th) {
background: rgba(24, 160, 88, 0.12) !important;
}
:deep(.kingdee-process-table .n-data-table-td) {
background-color: var(--n-color) !important;
}
:deep(.kingdee-process-table .n-data-table-tr--striped .n-data-table-td) {
background-color: var(--n-action-color) !important;
}
.kingdee-expand-empty {
margin: 4px 8px 8px 36px;
padding: 12px 14px;
font-size: 13px;
color: var(--n-text-color-3);
border: 1px dashed var(--n-border-color);
border-radius: 6px;
background: var(--n-action-color);
}
</style>

View File

@ -34,7 +34,7 @@
<!-- 工具栏 -->
<div class="table-toolbar">
<n-space>
<n-button
<!--<n-button
size="small"
type="primary"
@click="handleAdd"
@ -42,15 +42,15 @@
<template #icon><n-icon><AddOutline /></n-icon></template>
新增/补单
</n-button>
<!-- <n-button @click="importModalVisible = true">
<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">
</n-button>
<n-button type="error" :disabled="selectedIds.length === 0" @click="handleBatchDelete">
<template #icon><n-icon><TrashOutline /></n-icon></template>
删除
</n-button> -->
@ -117,16 +117,11 @@
</n-form-item>
</n-gi> -->
<n-gi>
<n-form-item label="项目名称" path="projectCode">
<!-- <n-input v-if="formData.id" v-model:value="formData.projectName" disabled placeholder="请选择项目名称" />
-->
<n-form-item label="项目名称" path="project">
<n-input v-if="formData.id" v-model:value="formData.projectName" disabled placeholder="请选择项目" />
<!--@search="xmhand"-->
<n-select
v-else
v-model:value="formData.projectCode"
v-model:value="formData.projectId"
filterable
placeholder="请选择项目"
:options="xmlist"
@ -350,77 +345,39 @@
</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="kingdeeModalVisible"
preset="card"
:title="kingdeeModalTitle"
class="kingdee-modal"
:style="{ width: '96vw', maxWidth: '1920px' }"
:content-style="{ padding: '16px 24px', minHeight: '72vh' }"
:mask-closable="false"
:closable="true"
:close-on-esc="false"
>
<KingdeeVue
:kingdeeTableData="kingdeeTableData"
:selectedId="kingdeeOrderOtemId"
@close-modal="kingdeeModalVisible = false"
@holdTemporarilyCallback="holdTemporarilySave"
@synchronizationCallback="synchronizationSave"
@reCrawlCallback="reCrawlReorderForm"/>
</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
} from 'naive-ui'
import {
SearchOutline,
RefreshOutline,
AddOutline,
//TrashOutline,
//CreateOutline,
// CloudUploadOutline,
// DownloadOutline
} from '@vicons/ionicons5'
import {
orderItemApi,
type OrderItem
} from '@/api/orderItem'
import { ref, reactive, h, onMounted } from 'vue'
import { NButton, NSpace, NIcon, useMessage, useDialog, type UploadCustomRequestOptions} from 'naive-ui'
import { orderItemApi, type OrderItem } from '@/api/orderItem'
import { useUserStore } from '@/stores/user'
import { VueDraggable } from 'vue-draggable-plus'
// import Gxitem from './gxitem.vue'
import KingdeeVue from '@/views/biz/kingdee/index.vue'
import { type KingdeePrdMo, type KingdeeProcessRoute } from '@/api/orderProject'
import { userApi } from '@/api/system'
const message = useMessage()
@ -632,19 +589,18 @@ const columns = [
align:'center',
title: '操作',
key: 'actions',
width: 140,
width: 190,
fixed: 'right',
render(row:any) {
const buttons:any = []
if(hasPermission('biz:orderItem:edit')){
buttons.push(h(NButton, {
size: 'small',
type:'primary',
ghost:true,
onClick: () => { handleEdit(row) } },
//{ default: () => [h(NIcon, null, { default: () => h(CreateOutline) }), ' ' ]}
{ default: () => '编辑'}
))
}
@ -657,6 +613,15 @@ const columns = [
{ default: () => '派工'}
))
}
if(hasPermission('biz:orderItem:reorderForm')){
buttons.push(h(NButton, {
size: 'small',
type:'info',
ghost:true,
onClick: () => handleReorderForm(row, false) }, //, disabled: row.starter !==1
{ default: () => '补单'}
))
}
return buttons.length > 0 ? h(NSpace, {justify:'center'}, { default: () => buttons }) : '-'
@ -779,31 +744,14 @@ let xmlist = ref<any>([])
let xmloading = ref(false)
function xmhand() {
async function xmhand() {
xmloading.value = true
orderItemApi.xmoptions({
// page: 1,
// pageSize: 100,
// username: v,
}).then((rps:any) =>{
if(rps && rps.length > 0){
xmlist.value = rps.map((n:any) => {
return {
label:n.label,
value:n.value+''
}
})
}
xmloading.value = false
}).catch(() => {
xmloading.value = false
})
xmlist.value = await orderItemApi.xmoptions({});
xmloading.value = false
}
let wllist = ref<any>([])
function xmselupdate(v:any,opt:any) {
// console.log(v,'sle')
// console.log(opt,'opt')
planList.value.splice(0)
wllist.value.splice(0)
formData.code = ''
@ -811,6 +759,7 @@ function xmselupdate(v:any,opt:any) {
formData.routeCode = ''
formData.proWorkshop = ''
formData.projectName = opt.label
formData.projectCode = opt?.additionParams?.projectCode || ''
if(v){
wlhand(opt.value)
}
@ -819,29 +768,73 @@ function xmselupdate(v:any,opt:any) {
//
let wlloading = ref(false)
function wlhand(v:any) {
async function wlhand(v:any) {
wlloading.value = true
orderItemApi.wloptions({
projectId:v
// page: 1,
// pageSize: 100,
// username: v
}).then((rps:any) =>{
if(rps && rps.length > 0){
wllist.value = rps.map((n:any) => {
return {
label:n.label,
value:n.value+''
}
})
}
console.log(yglist.value,'12')
wlloading.value = false
}).catch(() => {
wlloading.value = false
})
wllist.value = await orderItemApi.wloptions({projectId:v });
wlloading.value = false
}
const kingdeeOrderOtemId = ref<number | null>(null) // ID
const kingdeeModalVisible = ref(false)
const kingdeeModalTitle = ref('金蝶生产订单')
const kingdeeLoading = ref(false)
type KingdeeMoTableRow = Omit<KingdeePrdMo, 'children'> & { processRoutes: KingdeeProcessRoute[] }
const kingdeeTableData = ref<KingdeeMoTableRow[]>([])
// const kingdeeExpandedKeys = ref<Array<string | number>>([])
async function reCrawlReorderForm(id:number,reCrawl:Boolean){
try {
const data = await orderItemApi.preCreationInfo(id, {reCrawl:reCrawl})
kingdeeTableData.value = (Array.isArray(data) ? data : []).map((mo) => {
const { children, ...rest } = mo
const routes = [...(children ?? [])].sort((a, b) => (a.operNumber ?? 0) - (b.operNumber ?? 0)).map((r) => ({
...r,
planStartTime: r.planStartTime ?? null,
planFinishTime: r.planFinishTime ?? null,
}))
return { ...rest, processRoutes: routes }
})
} finally {
kingdeeLoading.value = false
}
}
async function handleReorderForm(row:OrderItem, reCrawl:Boolean){
if (!row.id) {
message.warning('缺少物料订单ID无法查询')
return
}
kingdeeOrderOtemId.value = row.id
kingdeeModalTitle.value = `金蝶生产订单${row.code ? ` - ${row.code}` : ''}`
kingdeeModalVisible.value = true
kingdeeLoading.value = true
reCrawlReorderForm(row.id, false)
kingdeeLoading.value = false
}
// 稿
async function holdTemporarilySave(id: number, data: KingdeePrdMo[]) {
try {
// processRoutes children
await orderItemApi.holdTemporarilySave(id, data)
} catch (error) {
//
}
}
//
async function synchronizationSave(id: number, data: KingdeePrdMo[]) {
try {
// processRoutes children
await orderItemApi.synchronizationSave(id, data)
} catch (error) {
//
}
}
//
function handleEdit(row: OrderItem) {
modalTitle.value = '编辑生产订单'

View File

@ -148,48 +148,13 @@
:closable="false"
:close-on-esc="false"
>
<div class="kingdee-toolbar">
<n-space>
<n-button
size="small"
:disabled="kingdeeLoading || !kingdeeTableData.length"
@click="kingdeeToggleExpandAll"
>
{{ kingdeeAllExpanded ? '全部收起' : '全部展开' }}
</n-button>
<n-button
size="small"
type="primary"
:disabled="kingdeeLoading || !kingdeeTableData.length"
@click="handleGanttSchedule"
>
<template #icon><n-icon><CalendarOutline /></n-icon></template>
甘特图排产
</n-button>
</n-space>
</div>
<n-data-table
v-model:expanded-row-keys="kingdeeExpandedKeys"
:columns="kingdeeMoColumns"
:data="kingdeeTableData"
:loading="kingdeeLoading"
:row-key="kingdeeMoRowKey"
:scroll-x="kingdeeMoScrollX"
:max-height="kingdeeTableMaxHeight"
:row-class-name="kingdeeMoRowClassName"
size="small"
/>
<template #footer>
<n-space justify="end">
<n-button type="info" :disabled="kingdeeLoading" @click="handleSyncOrderAndPlan">
同步订单计划
</n-button>
<n-button type="primary" :disabled="kingdeeLoading" @click="handleSaveDraft">
保存草稿
</n-button>
<n-button @click="kingdeeModalVisible = false">关闭</n-button>
</n-space>
</template>
<KingdeeVue
:kingdeeTableData="kingdeeTableData"
:selectedId="kingdeeCurrentProjectId"
@close-modal="kingdeeModalVisible = false"
@holdTemporarilyCallback="handleSaveDraft"
@synchronizationCallback="handleSyncOrderAndPlan"
@reCrawlCallback="reCrawlReorderForm"/>
</n-modal>
<!-- 导入弹窗 -->
@ -235,6 +200,9 @@ import { useUserStore } from '@/stores/user'
import { useRouter, useRoute } from 'vue-router'
import KingdeeVue from '@/views/biz/kingdee/index.vue'
const message = useMessage()
const dialog = useDialog()
const userStore = useUserStore()
@ -451,7 +419,7 @@ const columns: DataTableColumns<OrderProject> = [
const buttons = []
if (hasPermission('biz:orderProject:getKingdeeOrder')) {
buttons.push(
h(NButton, { size: 'small', quaternary: true, type: 'info', onClick: () => handleKingdeeQuery(row) }, {
h(NButton, { size: 'small', quaternary: true, type: 'info', onClick: () => handleKingdeeQuery(row, false) }, {
default: () => [h(NIcon, null, { default: () => h(EyeOutline) }), ' 预生产查询']
})
)
@ -691,8 +659,29 @@ function handleGanttSchedule() {
router.push('/biz/orderProject/gantt')
}
async function reCrawlReorderForm(id:number,reCrawl:Boolean){
try {
const data = await orderProjectApi.getKingdeeOrder(id,{reCrawl:reCrawl})
kingdeeTableData.value = (Array.isArray(data) ? data : []).map((mo) => {
const { children, ...rest } = mo
const routes = [...(children ?? [])]
.sort((a, b) => (a.operNumber ?? 0) - (b.operNumber ?? 0))
.map((r) => normalizeKingdeeProcessRoute({
...r,
planStartTime: r.planStartTime ?? null,
planFinishTime: r.planFinishTime ?? null,
}))
return { ...rest, processRoutes: routes }
})
if (kingdeeTableData.value.length === 0) {
message.info('未查询到金蝶生产订单数据')
}
} finally {
kingdeeLoading.value = false
}
}
//
async function handleKingdeeQuery(row: OrderProject) {
async function handleKingdeeQuery(row: OrderProject,reCrawl:Boolean) {
if (!row.id) {
message.warning('缺少项目ID无法查询')
return
@ -703,70 +692,98 @@ async function handleKingdeeQuery(row: OrderProject) {
kingdeeLoading.value = true
kingdeeTableData.value = []
kingdeeExpandedKeys.value = []
try {
const data = await orderProjectApi.getKingdeeOrder(row.id)
kingdeeTableData.value = (Array.isArray(data) ? data : []).map((mo) => {
const { children, ...rest } = mo
const routes = [...(children ?? [])]
.sort((a, b) => (a.operNumber ?? 0) - (b.operNumber ?? 0))
.map((r) => normalizeKingdeeProcessRoute({
...r,
planStartTime: r.planStartTime ?? null,
planFinishTime: r.planFinishTime ?? null,
}))
return { ...rest, processRoutes: routes }
})
if (kingdeeTableData.value.length === 0) {
message.info('未查询到金蝶生产订单数据')
}
} finally {
kingdeeLoading.value = false
}
reCrawlReorderForm(row.id,reCrawl)
// try {
// const data = await orderProjectApi.getKingdeeOrder(row.id)
// kingdeeTableData.value = (Array.isArray(data) ? data : []).map((mo) => {
// const { children, ...rest } = mo
// const routes = [...(children ?? [])]
// .sort((a, b) => (a.operNumber ?? 0) - (b.operNumber ?? 0))
// .map((r) => normalizeKingdeeProcessRoute({
// ...r,
// planStartTime: r.planStartTime ?? null,
// planFinishTime: r.planFinishTime ?? null,
// }))
// return { ...rest, processRoutes: routes }
// })
// if (kingdeeTableData.value.length === 0) {
// message.info('')
// }
// } finally {
// kingdeeLoading.value = false
// }
}
// 稿
async function handleSaveDraft() {
if (!kingdeeCurrentProjectId.value) return
kingdeeLoading.value = true
// 稿
// async function holdTemporarilyCallback(id: number, data: KingdeePrdMo[]) {
// await orderProjectApi.saveKingdeeOrderDraft(id, data)
// }
// 稿
async function handleSaveDraft(id: number, data: KingdeePrdMo[]) {
try {
// processRoutes children
const draftData = kingdeeTableData.value.map(mo => {
const { processRoutes, ...rest } = mo
return { ...rest, children: processRoutes } as KingdeePrdMo
})
await orderProjectApi.saveKingdeeOrderDraft(kingdeeCurrentProjectId.value, draftData)
message.success('草稿保存成功')
await orderProjectApi.saveKingdeeOrderDraft(id, data)
} catch (error) {
//
} finally {
kingdeeLoading.value = false
}
}
}
//
async function handleSyncOrderAndPlan() {
if (!kingdeeCurrentProjectId.value) return
kingdeeLoading.value = true
async function handleSyncOrderAndPlan(id: number, data: KingdeePrdMo[]) {
try {
// processRoutes children
const draftData = kingdeeTableData.value.map(mo => {
const { processRoutes, ...rest } = mo
return { ...rest, children: processRoutes } as KingdeePrdMo
})
await orderProjectApi.saveKingdeeOrderAndPlan(kingdeeCurrentProjectId.value, draftData)
message.success('同步订单计划成功')
kingdeeModalVisible.value = false
await orderProjectApi.saveKingdeeOrderAndPlan(id, data)
} catch (error) {
//
} finally {
kingdeeLoading.value = false
}
}
}
// // 稿
// async function handleSaveDraft() {
// if (!kingdeeCurrentProjectId.value) return
// kingdeeLoading.value = true
// try {
// // processRoutes children
// const draftData = kingdeeTableData.value.map(mo => {
// const { processRoutes, ...rest } = mo
// return { ...rest, children: processRoutes } as KingdeePrdMo
// })
// await orderProjectApi.saveKingdeeOrderDraft(kingdeeCurrentProjectId.value, draftData)
// message.success('稿')
// } catch (error) {
// //
// } finally {
// kingdeeLoading.value = false
// }
// }
//
// async function handleSyncOrderAndPlan() {
// if (!kingdeeCurrentProjectId.value) return
// kingdeeLoading.value = true
// try {
// // processRoutes children
// const draftData = kingdeeTableData.value.map(mo => {
// const { processRoutes, ...rest } = mo
// return { ...rest, children: processRoutes } as KingdeePrdMo
// })
// await orderProjectApi.saveKingdeeOrderAndPlan(kingdeeCurrentProjectId.value, draftData)
// message.success('')
// kingdeeModalVisible.value = false
// } catch (error) {
// //
// } finally {
// kingdeeLoading.value = false
// }
// }
//
function handleDelete(row: OrderProject) {
dialog.warning({