Compare commits

...

11 Commits

@ -24,7 +24,7 @@ export const RecipePointApi = {
return await request.post({ url: `/iot/recipe-point/create`, data })
},
updateRecipePoint: async (data: RecipePointVO) => {
return await request.post({ url: `/iot/recipe-point/update`, data })
return await request.put({ url: `/iot/recipe-point/update`, data })
},
deleteRecipePoint: async (id: number) => {
return await request.delete({ url: `/iot/recipe-point/delete?id=` + id })

@ -180,6 +180,11 @@
prop="productNames"
min-width="180"
/>
<el-table-column label="生产计划编码" align="center" prop="planCode" min-width="160">
<template #default="scope">
<span>{{ scope.row.planCode ? scope.row.planCode : '-' }}</span>
</template>
</el-table-column>
<!-- <el-table-column label="客户" align="center" prop="customerName" /> -->
<el-table-column
:label="t('ErpStock.Out.outTime')"

@ -183,7 +183,7 @@
v-for="unit in unitList"
:key="unit.id"
:label="unit.name"
:value="unit.id"
:value="String(unit.id)"
/>
</el-select>
</el-form-item>

@ -205,6 +205,23 @@ const buildQueryParams = () => {
}
}
const refreshManual = async () => {
if (!props.recipeId) {
list.value = []
total.value = 0
return
}
loading.value = true
try {
await ensureUnitList()
const data = await RecipePointRecordApi.getRecipePointRecordPage(buildQueryParams())
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
const getList = async () => {
if (!props.recipeId) {
list.value = []
@ -256,4 +273,6 @@ watch(
getList()
}
)
defineExpose({ refreshManual })
</script>

@ -84,10 +84,10 @@
</div>
<template #footer>
<el-button @click="submitForm" type="primary">
<el-button @click="submitForm" type="primary" :loading="submitLoading" :disabled="submitLoading">
{{ t('RecipeManagement.RecipeLibrary.readDialogSubmitButtonText') }}
</el-button>
<el-button @click="visible = false">
<el-button @click="visible = false" :disabled="submitLoading">
{{ t('RecipeManagement.RecipeLibrary.readDialogCancelButton') }}
</el-button>
</template>
@ -107,6 +107,7 @@ type PageResult<T> = { list: T[]; total: number }
const visible = ref(false)
const title = ref('')
const loading = ref(false)
const submitLoading = ref(false)
const hasExistingRecords = ref(false)
const recipeId = ref<string | number | undefined>(undefined)
@ -115,6 +116,9 @@ const total = ref(0)
const { t } = useI18n() //
const message = useMessage() //
const emit = defineEmits<{
(e: 'success'): void
}>()
const unitList = ref<ProductUnitVO[]>([])
@ -193,12 +197,19 @@ const open = async (options: {
defineExpose({ open })
const submitForm = async() => {
const submitForm = async () => {
if (submitLoading.value) return
submitLoading.value = true
console.log(list.value)
try {
await RecipePointRecordApi.createRecipePointRecordBatch(list.value as unknown as RecipePointRecordVO[])
await RecipeDeviceRecordApi.createRecipeDeviceRecordBatch(formulaLibraryId.value)
visible.value = false
message.success(t('common.createSuccess'))
emit('success')
} finally {
submitLoading.value = false
}
}

@ -102,10 +102,10 @@ v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" ro
</ContentWrap>
<ContentWrap v-if="detailVisible">
<FormulaLibraryDetailTabs :recipe-id="detailRecipeId" />
<FormulaLibraryDetailTabs ref="detailTabsRef" :recipe-id="detailRecipeId" />
</ContentWrap>
<FormulaLibraryReadDialog ref="readDialogRef" />
<FormulaLibraryReadDialog ref="readDialogRef" @success="handleReadSuccess" />
<Dialog :title="dialogTitle" v-model="dialogVisible" width="720px">
<el-form
@ -339,6 +339,11 @@ const openDialog = async (type: 'create' | 'update', row?: RecipePlanDetailVO) =
}
const readDialogRef = ref<InstanceType<typeof FormulaLibraryReadDialog>>()
const detailTabsRef = ref<InstanceType<typeof FormulaLibraryDetailTabs>>()
const handleReadSuccess = async () => {
await detailTabsRef.value?.refreshManual?.()
}
const checkRecipeRecords = async (recipeId: string | number) => {
const params = {
@ -380,6 +385,7 @@ const handleRead = async (row: RecipePlanDetailVO) => {
if (id != null) {
await RecipeDeviceRecordApi.createRecipeDeviceRecordBatch(id)
message.success(t('common.createSuccess'))
await handleReadSuccess()
return
}
}

@ -149,34 +149,28 @@
</el-col> -->
<el-col :span="24">
<el-form-item :label="t('EquipmentManagement.EquipmentLedger.criticalComponent')" prop="componentIds">
<el-cascader
v-model="criticalComponentCascaderValue"
:options="criticalComponentPagedOptions"
:props="cascaderProps"
filterable
<el-input
:model-value="criticalComponentDisplay"
readonly
clearable
collapse-tags
:show-all-levels="false"
class="device-ledger-selection-input"
:placeholder="t('EquipmentManagement.EquipmentLedger.placeholderComponentIds')"
class="!w-full"
@change="handleCriticalComponentChange"
@clear="clearCriticalComponent"
@click="openCriticalComponentDialog"
/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item :label="t('EquipmentManagement.EquipmentLedger.sparePart')" prop="beijianIds">
<el-cascader
v-model="beijianCascaderValue"
:options="beijianPagedOptions"
:props="cascaderProps"
filterable
<el-input
:model-value="beijianDisplay"
readonly
clearable
collapse-tags
:show-all-levels="false"
class="device-ledger-selection-input"
:placeholder="t('EquipmentManagement.EquipmentLedger.placeholderBeijianIds')"
class="!w-full"
@change="handleBeijianChange"
@clear="clearBeijian"
@click="openBeijianDialog"
/>
</el-form-item>
</el-col>
@ -199,6 +193,48 @@
</template>
</Dialog>
<el-dialog
v-model="criticalComponentDialogVisible"
title="选择关键件"
width="860px"
class="device-ledger-transfer-dialog"
append-to-body
>
<div class="device-ledger-transfer">
<el-transfer
v-model="criticalComponentDraft"
:data="criticalComponentTransferData"
filterable
:filter-placeholder="t('EquipmentManagement.EquipmentLedger.placeholderComponentIds')"
/>
</div>
<template #footer>
<el-button @click="criticalComponentDialogVisible = false">{{ t('common.cancel') }}</el-button>
<el-button type="primary" @click="confirmCriticalComponentDialog">{{ t('common.ok') }}</el-button>
</template>
</el-dialog>
<el-dialog
v-model="beijianDialogVisible"
title="选择备件"
width="860px"
class="device-ledger-transfer-dialog"
append-to-body
>
<div class="device-ledger-transfer">
<el-transfer
v-model="beijianDraft"
:data="beijianTransferData"
filterable
:filter-placeholder="t('EquipmentManagement.EquipmentLedger.placeholderBeijianIds')"
/>
</div>
<template #footer>
<el-button @click="beijianDialogVisible = false">{{ t('common.cancel') }}</el-button>
<el-button type="primary" @click="confirmBeijianDialog">{{ t('common.ok') }}</el-button>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { DeviceLedgerApi, DeviceLedgerVO } from '@/api/mes/deviceledger'
@ -287,31 +323,61 @@ const deviceTypeTree = ref<DeviceTypeTreeVO[]>([])
const users = ref<UserVO[]>([])
const criticalComponentOptions = ref<{ label: string; value: number }[]>([])
const beijianOptions = ref<{ label: string; value: number }[]>([])
const PAGE_SIZE = 10
const buildPagedOptions = (options: { label: string; value: number }[]) => {
const result: { label: string; value: string; children: { label: string; value: number }[] }[] = []
for (let i = 0; i < options.length; i += PAGE_SIZE) {
const pageIndex = result.length + 1
result.push({
label: String(pageIndex),
value: `page-${pageIndex}`,
children: options.slice(i, i + PAGE_SIZE).map((item) => ({
label: item.label,
value: item.value
}))
})
}
return result
const criticalComponentTransferData = computed(() =>
criticalComponentOptions.value.map((item) => ({ key: item.value, label: item.label }))
)
const beijianTransferData = computed(() =>
beijianOptions.value.map((item) => ({ key: item.value, label: item.label }))
)
const criticalComponentDialogVisible = ref(false)
const beijianDialogVisible = ref(false)
const criticalComponentDraft = ref<number[]>([])
const beijianDraft = ref<number[]>([])
const formatSelectedSummary = (ids: number[], options: { label: string; value: number }[]) => {
const optionMap = new Map<number, string>(options.map((item) => [item.value, item.label]))
const labels = ids.map((id) => optionMap.get(id)).filter((v): v is string => Boolean(v))
if (!labels.length) return ''
if (labels.length <= 3) return labels.join('、')
return `${labels.slice(0, 3).join('、')}…等${labels.length}`
}
const cascaderProps = { multiple: true, emitPath: false, checkStrictly: false }
const criticalComponentDisplay = computed(() =>
formatSelectedSummary(formData.value.componentIds ?? [], criticalComponentOptions.value)
)
const beijianDisplay = computed(() =>
formatSelectedSummary(formData.value.beijianIds ?? [], beijianOptions.value)
)
const clearCriticalComponent = () => {
formData.value.componentIds = []
}
const clearBeijian = () => {
formData.value.beijianIds = []
}
const criticalComponentCascaderValue = ref<(number | string)[]>([])
const beijianCascaderValue = ref<(number | string)[]>([])
const openCriticalComponentDialog = () => {
criticalComponentDraft.value = [...(formData.value.componentIds ?? [])]
criticalComponentDialogVisible.value = true
}
const openBeijianDialog = () => {
beijianDraft.value = [...(formData.value.beijianIds ?? [])]
beijianDialogVisible.value = true
}
const criticalComponentPagedOptions = computed(() => buildPagedOptions(criticalComponentOptions.value))
const beijianPagedOptions = computed(() => buildPagedOptions(beijianOptions.value))
const confirmCriticalComponentDialog = () => {
const validMap = new Set(criticalComponentOptions.value.map((item) => item.value))
const selected = Array.from(new Set(criticalComponentDraft.value.map((v) => Number(v)).filter((v) => validMap.has(v))))
formData.value.componentIds = selected
criticalComponentDialogVisible.value = false
}
const confirmBeijianDialog = () => {
const validMap = new Set(beijianOptions.value.map((item) => item.value))
const selected = Array.from(new Set(beijianDraft.value.map((v) => Number(v)).filter((v) => validMap.has(v))))
formData.value.beijianIds = selected
beijianDialogVisible.value = false
}
const ensureOptionsLoaded = async () => {
const [deviceTypeRes, userRes, criticalRes, beijianRes] = await Promise.all([
@ -336,48 +402,6 @@ const ensureOptionsLoaded = async () => {
})
}
watch(
() => formData.value.componentIds,
(ids) => {
criticalComponentCascaderValue.value = Array.isArray(ids) ? [...ids] : []
},
{ immediate: true }
)
watch(
() => formData.value.beijianIds,
(ids) => {
beijianCascaderValue.value = Array.isArray(ids) ? [...ids] : []
},
{ immediate: true }
)
const handleCriticalComponentChange = (values: (number | string)[]) => {
const validIds = new Set<number>()
const validMap = new Set(criticalComponentOptions.value.map((item) => item.value))
for (const v of values) {
const num = Number(v)
if (!Number.isNaN(num) && validMap.has(num)) {
validIds.add(num)
}
}
formData.value.componentIds = Array.from(validIds)
criticalComponentCascaderValue.value = Array.from(validIds)
}
const handleBeijianChange = (values: (number | string)[]) => {
const validIds = new Set<number>()
const validMap = new Set(beijianOptions.value.map((item) => item.value))
for (const v of values) {
const num = Number(v)
if (!Number.isNaN(num) && validMap.has(num)) {
validIds.add(num)
}
}
formData.value.beijianIds = Array.from(validIds)
beijianCascaderValue.value = Array.from(validIds)
}
/** 打开弹窗 */
const open = async (type: string, id?: number, defaultDeviceTypeId?: number) => {
dialogVisible.value = true
@ -468,4 +492,47 @@ const resetForm = () => {
:deep(.ellipsis-text){
max-width: 300px;
}
.device-ledger-transfer {
width: 100%;
overflow-x: auto;
}
.device-ledger-transfer :deep(.el-transfer) {
width: 100%;
min-width: 760px;
flex-wrap: nowrap;
}
.device-ledger-transfer :deep(.el-transfer-panel) {
flex: 1 0 340px;
width: 340px;
}
.device-ledger-transfer-dialog :deep(.el-dialog__body) {
padding-top: 8px;
}
.device-ledger-transfer-dialog .device-ledger-transfer :deep(.el-transfer-panel) {
height: 560px;
}
.device-ledger-transfer-dialog .device-ledger-transfer :deep(.el-transfer-panel__body) {
height: 520px;
}
.device-ledger-transfer-dialog .device-ledger-transfer :deep(.el-transfer-panel__list) {
height: 100%;
}
.device-ledger-transfer :deep(.el-transfer__buttons) {
flex: 0 0 72px;
padding: 0 12px;
}
.device-ledger-selection-input :deep(.el-input__inner) {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
</style>

@ -111,11 +111,11 @@
<el-table-column :label="t('ProductionPlan.FeedingRecord.tableWeightColumn')" align="center" prop="weight" />
<el-table-column :label="t('ProductionPlan.FeedingRecord.tableUserColumn')" align="center" prop="userName" />
<el-table-column :label="t('ProductionPlan.FeedingRecord.tableRemarkColumn')" align="center" prop="remark" />
<!-- <el-table-column label="状态" align="center" prop="recordStatus">
<el-table-column label="状态" align="center" prop="recordStatus">
<template #default="scope">
<dict-tag :type="DICT_TYPE.MES_FEEDING_RECORD_STATUS" :value="scope.row.recordStatus" />
</template>
</el-table-column> -->
</el-table-column>
<el-table-column
:label="t('ProductionPlan.FeedingRecord.tableFeedingTimeColumn')"
align="center"

@ -21,7 +21,7 @@
v-for="item in taskList"
:key="item.id"
:label="item.code"
:value="item.id"
:value="String(item.id)"
/>
</el-select>
</el-form-item>

@ -98,7 +98,7 @@
highlight-current-row
@current-change="handleCurrentChange"
>
<el-table-column :label="t('ProductionPlan.TaskSummary.tableTaskCodeColumn')" align="center" prop="code" width="150px"/>
<el-table-column :label="t('ProductionPlan.TaskSummary.tableTaskCodeColumn')" align="center" prop="code" width="200px"/>
<el-table-column :label="t('ProductionPlan.TaskSummary.tableOrderDateColumn')" align="center" prop="orderDate" :formatter="dateFormatter2" />
<el-table-column :label="t('ProductionPlan.TaskSummary.tableDeliveryDateColumn')" align="center" prop="deliveryDate" :formatter="dateFormatter2"/>
<el-table-column :label="t('ProductionPlan.TaskSummary.tableStatusColumn')" align="center" prop="status">

@ -57,7 +57,7 @@
>
<template #default="scope">
<UploadImg
v-if="String(scope.row.zjResult) === '0'"
v-if="String(scope.row.zjResult) === '0' && !readOnly"
v-model="imageMap[String(scope.row.id)]"
:drag="false"
:show-btn-text="false"
@ -78,7 +78,7 @@
<el-table-column label="输入值" align="center" min-width="150">
<template #default="scope">
<el-input
v-if="String(scope.row.zjResult) === '0'"
v-if="String(scope.row.zjResult) === '0' && !readOnly"
v-model="scope.row.textInput"
clearable
placeholder="请输入"
@ -119,7 +119,7 @@
>
<template #default="scope">
<el-radio-group
v-if="String(scope.row.zjResult) === '0'"
v-if="String(scope.row.zjResult) === '0' && !readOnly"
v-model="decisionMap[String(scope.row.id)]"
>
<el-radio :label="1">{{ t('QualityManagement.TicketResultDialog.pass') }}</el-radio>
@ -159,7 +159,7 @@
type="primary"
@click="handleSave"
:loading="submitLoading"
:disabled="submitLoading || !isAllSelected()"
:disabled="readOnly || submitLoading || !isAllSelected()"
>
{{ t('QualityManagement.TicketResultDialog.save') }}
</el-button>
@ -179,6 +179,7 @@ const dialogVisible = ref(false)
const dialogTitle = ref(t('QualityManagement.TicketResultDialog.moduleName'))
const loading = ref(false)
const submitLoading = ref(false)
const readOnly = ref(false)
const emit = defineEmits(['success'])
const message = useMessage()
@ -196,12 +197,13 @@ const queryParams = reactive({
pageSize: 10,
})
const open = async (options: { id: number; status?: string | number; cancelReason?: string }) => {
const open = async (options: { id: number; status?: string | number; cancelReason?: string; readOnly?: boolean }) => {
dialogVisible.value = true
dialogTitle.value = t('QualityManagement.TicketResultDialog.moduleName')
taskId.value = options.id
status.value = options.status
cancelReason.value = options.cancelReason
readOnly.value = !!options.readOnly
for (const key of Object.keys(decisionMap)) delete decisionMap[key]
for (const key of Object.keys(imageMap)) delete imageMap[key]
queryParams.pageNo = 1
@ -250,6 +252,7 @@ const getRowKey = (row: ZjTaskResultVO) => {
}
const handleSave = async () => {
if (readOnly.value) return
if (!taskId.value) {
message.error('任务标识不存在,无法保存')
return

@ -122,7 +122,7 @@ type="success" plain @click="handleExport" :loading="exportLoading"
<DictTag :type="'job_status'" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column :label="t('QualityManagement.ZjTask.ticketCode')" align="center" prop="ticketCode" />
<el-table-column :label="t('QualityManagement.ZjTask.ticketCode')" align="center" prop="ticketCode" width="200px"/>
<el-table-column :label="t('QualityManagement.ZjTask.orgType')" align="center" prop="orgType">
<template #default="scope">
<DictTag :type="DICT_TYPE.MES_ORG_TYPE" :value="scope.row.orgType" />
@ -153,7 +153,6 @@ type="success" plain @click="handleExport" :loading="exportLoading"
<el-table-column :label="t('QualityManagement.ZjTask.operate')" align="center" min-width="160px">
<template #default="scope">
<el-button
v-if="scope.row.status === 0"
link
type="warning"
@click.stop="handleRowClick(scope.row)"
@ -258,9 +257,21 @@ const openForm = (type: string, row?: ZjTaskVO) => {
formRef.value.open(type, row)
}
const isInspected = (row: ZjTaskVO) => {
const result = (row as any)?.result
if (result === 1 || result === '1' || result === 2 || result === '2') return true
const status = (row as any)?.status
return String(status ?? '') !== '0'
}
const handleRowClick = (row: ZjTaskVO) => {
if (!row?.id) return
resultDialogRef.value?.open({ id: row.id, status: row.status, cancelReason: row.cancelReason })
resultDialogRef.value?.open({
id: row.id,
status: row.status,
cancelReason: row.cancelReason,
readOnly: isInspected(row),
})
}
const handleDelete = async (id: number) => {

@ -39,14 +39,12 @@
<el-table-column :label="t('QualityManagement.ZjTask.operate')" align="center" width="160" fixed="right">
<template #default="scope">
<el-button
v-if="scope.row.status === 0"
link
type="warning"
@click.stop="handleRowClick(scope.row)"
>
{{ t('QualityManagement.ZjTask.inspect') }}
</el-button>
<span v-else>-</span>
</template>
</el-table-column>
</el-table>
@ -100,9 +98,21 @@ const getList = async () => {
}
}
const isInspected = (row: ZjTaskListRow) => {
const result = (row as any)?.result
if (result === 1 || result === '1' || result === 2 || result === '2') return true
const status = (row as any)?.status
return String(status ?? '') !== '0'
}
const handleRowClick = (row: ZjTaskListRow) => {
if (!row?.id) return
resultDialogRef.value?.open({ id: row.id, status: row.status, cancelReason: (row as any).cancelReason })
resultDialogRef.value?.open({
id: row.id,
status: row.status,
cancelReason: (row as any).cancelReason,
readOnly: isInspected(row),
})
}
watch(

Loading…
Cancel
Save