Merge branch 'master' of https://git.evo-techina.com/sgc/mes-vue
This commit is contained in:
commit
1ad2bd9551
@ -185,5 +185,12 @@ export const deviceApi = {
|
||||
method:"get",
|
||||
params
|
||||
})
|
||||
},
|
||||
|
||||
getById(deviceId:number) {
|
||||
return request({
|
||||
url:`/biz/device/getByid/${deviceId}`,
|
||||
method:"get"
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -103,9 +103,9 @@ export function exportNccode(params:any) {
|
||||
}
|
||||
|
||||
//加载全部NC代码
|
||||
export function loadAllNcCode() {
|
||||
export function loadAllNcCode(id:number) {
|
||||
return request({
|
||||
url: `biz/ncCode/loadAllNcCode`,
|
||||
url: `biz/ncCode/loadAllNcCode/${id}`,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
@ -42,6 +42,8 @@ export interface OrderProcessPlan {
|
||||
|
||||
workshopId?: number | null
|
||||
|
||||
leftoverMaterials?:number | null
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -189,6 +191,8 @@ export interface OrderProcessPlanVO {
|
||||
|
||||
currentOperNumber?: number
|
||||
|
||||
leftoverMaterials?:number
|
||||
|
||||
processList?: ProcessPlanItemVO[]
|
||||
|
||||
}
|
||||
|
||||
76
src/api/refillRecord.ts
Normal file
76
src/api/refillRecord.ts
Normal file
@ -0,0 +1,76 @@
|
||||
import { request } from '@/utils/request'
|
||||
|
||||
// 补料记录 类型定义
|
||||
export interface RefillRecord {
|
||||
id?: number
|
||||
|
||||
processId?: number
|
||||
|
||||
num?: number
|
||||
|
||||
createTime?: string
|
||||
|
||||
createBy?: number
|
||||
|
||||
}
|
||||
|
||||
// 补料记录 API
|
||||
export const refillRecordApi = {
|
||||
// 分页查询
|
||||
page(params: { page: number; pageSize: number; id?: number }) {
|
||||
return request({ url: '/biz/refillRecord/page', method: 'get', params })
|
||||
},
|
||||
|
||||
// 获取详情
|
||||
detail(id: number) {
|
||||
return request({ url: `/biz/refillRecord/${id}`, method: 'get' })
|
||||
},
|
||||
|
||||
// 新增
|
||||
create(data: RefillRecord) {
|
||||
return request({ url: '/biz/refillRecord', method: 'post', data })
|
||||
},
|
||||
|
||||
// 修改
|
||||
update(data: RefillRecord) {
|
||||
return request({ url: '/biz/refillRecord', method: 'put', data })
|
||||
},
|
||||
|
||||
// 删除
|
||||
delete(ids: number[]) {
|
||||
return request({ url: `/biz/refillRecord/${ids.join(',')}`, method: 'delete' })
|
||||
},
|
||||
|
||||
// 导出
|
||||
export(params?: { ids?: number[]; id?: 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
|
||||
return request({ url: `/biz/refillRecord/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/refillRecord/import`,
|
||||
method: 'post',
|
||||
data: formData,
|
||||
headers: { 'Content-Type': 'multipart/form-data' }
|
||||
})
|
||||
},
|
||||
|
||||
// 下载导入模板
|
||||
downloadTemplate() {
|
||||
return request({ url: `/biz/refillRecord/template`, method: 'get', responseType: 'blob' })
|
||||
},
|
||||
|
||||
//查询该工序补料数量
|
||||
getRefillNumByProcessId(processId:number){
|
||||
return request({
|
||||
url:`/biz/refillRecord/getRefillNumByProcessId/${processId}`,
|
||||
method:"get"
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -390,6 +390,7 @@ import { noticeApi, chatApi, type SysNotice, type ChatMessage } from '@/api/mess
|
||||
import { iconMap as externalIconMap } from '@/utils/icons'
|
||||
import ErrorReportModal from "@/components/ErrorReportModal.vue";
|
||||
import {errorNotificationApi} from "@/api/errorNotification.ts";
|
||||
import {deviceApi} from "@/api/device.ts";
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
@ -612,6 +613,8 @@ function stripHtml(html: string | undefined): string {
|
||||
const notice = ref<SysNotice>( {})
|
||||
async function handleNoticeClick(item: SysNotice) {
|
||||
notice.value = item
|
||||
const res = await deviceApi.getById(Number(notice.value.deviceId))
|
||||
notice.value.deviceName = res
|
||||
//异常填报直接弹窗
|
||||
showErrorReportModal.value = true
|
||||
// 标记已读
|
||||
|
||||
@ -157,6 +157,7 @@
|
||||
@outsource="(p) => openOutsource(order, p)"
|
||||
@view-model="(p) => openPlmModel(order, p)"
|
||||
@submit-detail = "(p) => openDetailModel(order,p)"
|
||||
@handleLeftoverMaterial = "(p) => openLeftoverMaterialModel(order,p)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -608,11 +609,69 @@
|
||||
</n-space>
|
||||
</template>
|
||||
</n-modal>
|
||||
|
||||
<!--补料弹窗-->
|
||||
<n-modal v-model:show="leftMaterialVisible" preset="card" title="工序补料" style="width: 800px">
|
||||
<n-card>
|
||||
<n-grid :cols="2">
|
||||
<n-gi>
|
||||
<span class="pgClass">物料编码:</span>
|
||||
<span>{{leftMaterialOrder.materialCode}}</span>
|
||||
</n-gi>
|
||||
<n-gi>
|
||||
<span class="pgClass">物料名称:</span>
|
||||
<span>{{leftMaterialOrder.materialName}}</span>
|
||||
</n-gi>
|
||||
</n-grid>
|
||||
<n-grid :cols="2">
|
||||
<n-gi>
|
||||
<span class="pgClass">工序编号:</span>
|
||||
<span>{{leftMaterialPlan.processCode}}</span>
|
||||
</n-gi>
|
||||
<n-gi>
|
||||
<span class="pgClass">工序名称:</span>
|
||||
<span>{{leftMaterialPlan.processName}}</span>
|
||||
</n-gi>
|
||||
</n-grid>
|
||||
<n-grid :cols="2">
|
||||
<n-gi>
|
||||
<span class="pgClass">可补料数:</span>
|
||||
<span style="color: #2080f0; font-weight: 600">{{leftMaterialPlan.enablefill}}</span>
|
||||
</n-gi>
|
||||
</n-grid>
|
||||
</n-card>
|
||||
<n-form ref="dispatchformRef" :model="planForm"
|
||||
label-placement="left"
|
||||
:rules="dispatchrules"
|
||||
style="margin-top: 10px;"
|
||||
label-width="80">
|
||||
<n-grid :cols="2">
|
||||
<n-gi :span="24">
|
||||
<n-form-item label="补料数量" path="leftoverMaterials">
|
||||
<n-input-number
|
||||
v-model:value="planForm.leftoverMaterials"
|
||||
:min="0"
|
||||
:max="leftMaterialPlan.enablefill"
|
||||
placeholder="输入补料数量"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-gi>
|
||||
</n-grid>
|
||||
</n-form>
|
||||
<template #footer>
|
||||
<n-space justify="end">
|
||||
<n-button size="small" @click="leftMaterialVisible = false">取消</n-button>
|
||||
<n-button size="small" type="primary" @click="submitLeftoverMaterial">确定</n-button>
|
||||
</n-space>
|
||||
</template>
|
||||
</n-modal>
|
||||
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted, h, computed, type Component } from 'vue'
|
||||
import {ref, reactive, onMounted, h, computed, type Component, toRaw} from 'vue'
|
||||
import {
|
||||
NButton, NSpace, NIcon, NTag, NSpin, NModal, NForm, NFormItem, NGrid, NGi,
|
||||
NInput, NInputNumber, NDatePicker, NCheckbox, NEmpty, NPagination, NDropdown, NDescriptions,
|
||||
@ -635,7 +694,7 @@ import {
|
||||
type OrderProcessPlanVO,
|
||||
type ProcessPlanItemVO,
|
||||
type OutsourcingOptions,
|
||||
type OutsourcingProcessOption,
|
||||
type OutsourcingProcessOption, OrderProcessPlan,
|
||||
} from '@/api/orderProcessPlan'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
import ProcessFlowStepper from './components/ProcessFlowStepper.vue'
|
||||
@ -646,6 +705,7 @@ import type { PlmModelOpenContext } from '@/api/plmModel'
|
||||
import Pgitem from './pgitem.vue'
|
||||
import ReportDetailPage from "@/views/biz/orderProcessPlan/components/ReportDetail.vue";
|
||||
import OrderReportDetailPage from "@/views/biz/orderProcessPlan/components/OrderReportDetail.vue";
|
||||
import {refillRecordApi} from "@/api/refillRecord.ts";
|
||||
|
||||
|
||||
const message = useMessage()
|
||||
@ -754,11 +814,48 @@ const processId = ref<number | null>(null)
|
||||
function openDetailModel(order:ProcessPlanItemVO,process?:OrderProcessPlanVO) {
|
||||
|
||||
submitLogModalVisible.value = true
|
||||
console.log(process.planId)
|
||||
processId.value = process.planId
|
||||
|
||||
}
|
||||
|
||||
const leftMaterialVisible = ref<Boolean>(false)
|
||||
const leftMaterialOrder = ref<ProcessPlanItemVO>({})
|
||||
const leftMaterialPlan = ref<OrderProcessPlanVO>({})
|
||||
const planForm = ref<OrderProcessPlanVO>({})
|
||||
|
||||
//补料模板
|
||||
async function openLeftoverMaterialModel(order:ProcessPlanItemVO,process?:OrderProcessPlanVO) {
|
||||
|
||||
//补料记录数量
|
||||
const res = await refillRecordApi.getRefillNumByProcessId(process.planId);
|
||||
leftMaterialVisible.value = true
|
||||
leftMaterialOrder.value = order
|
||||
leftMaterialPlan.value = process
|
||||
planForm.value.leftoverMaterials = 0;
|
||||
leftMaterialPlan.value.enablefill = Number(leftMaterialPlan.value.scrapQty) - Number(res);
|
||||
}
|
||||
|
||||
|
||||
//提交补料数据
|
||||
async function submitLeftoverMaterial(){
|
||||
const rawPlan = toRaw(leftMaterialPlan.value)
|
||||
let orderProcessPlan = {...rawPlan}
|
||||
try {
|
||||
//添加补料记录
|
||||
await refillRecordApi.create({processId:orderProcessPlan.planId,num:planForm.value.leftoverMaterials})
|
||||
message.success("补料成功")
|
||||
loadData()
|
||||
}catch (e) {
|
||||
console.log("补料异常:"+e)
|
||||
message.error("补料失败")
|
||||
}finally {
|
||||
leftMaterialVisible.value = false
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
const batchOptions = [
|
||||
{ label: '全部展开', key: 'expandAll' },
|
||||
{ label: '全部收起', key: 'collapseAll' },
|
||||
@ -1270,12 +1367,12 @@ function dispatchSubmit() {
|
||||
dispatchformRef.value?.validate((errors: any) => {
|
||||
// Naive UI:有 errors 表示校验失败
|
||||
if (errors) return
|
||||
if (total !== remainQty) {
|
||||
message.error(`派工总数量需等于待派数量 ${remainQty}(计划 ${dispatchform.quantity},已完成 ${dispatchform.completedQty ?? 0})`, {
|
||||
duration: 4000,
|
||||
})
|
||||
return
|
||||
}
|
||||
// if (total !== remainQty) {
|
||||
// message.error(`派工总数量需等于待派数量 ${remainQty}(计划 ${dispatchform.quantity},已完成 ${dispatchform.completedQty ?? 0})`, {
|
||||
// duration: 4000,
|
||||
// })
|
||||
// return
|
||||
// }
|
||||
|
||||
dispatchLoading.value = true
|
||||
// 提交时 quantity 仍传计划总数,避免把工序计划数量改成待派数
|
||||
|
||||
@ -51,7 +51,7 @@
|
||||
</div>
|
||||
<div class="flow-item">
|
||||
<span>剩余物料</span>
|
||||
<strong>{{ remainQty }}</strong>
|
||||
<strong>{{ leftoverMaterials }}</strong>
|
||||
</div>
|
||||
|
||||
<div class="flow-item">
|
||||
@ -106,6 +106,13 @@
|
||||
ghost
|
||||
@click="emit('submitDetail', process)"
|
||||
>汇报</n-button>
|
||||
<n-button
|
||||
:disabled="refillDisAbled"
|
||||
size="tiny"
|
||||
type="info"
|
||||
ghost
|
||||
@click="emit('handleLeftoverMaterial', process)"
|
||||
>补料</n-button>
|
||||
<n-button
|
||||
size="tiny"
|
||||
:type="process.processStatus === 4 ? 'success' : 'default'"
|
||||
@ -121,10 +128,12 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import {computed, onMounted, ref} from 'vue'
|
||||
import { NButton, NIcon, NProgress, NTag } from 'naive-ui'
|
||||
import { ChevronForwardOutline } from '@vicons/ionicons5'
|
||||
import { PROCESS_STATUS_MAP, type ProcessPlanItemVO } from '@/api/orderProcessPlan'
|
||||
import { refillRecordApi } from '@/api/refillRecord.ts'
|
||||
|
||||
|
||||
const props = defineProps<{
|
||||
process: ProcessPlanItemVO
|
||||
@ -153,6 +162,7 @@ const emit = defineEmits<{
|
||||
viewModel: [process: ProcessPlanItemVO]
|
||||
outsource: [process: ProcessPlanItemVO]
|
||||
submitDetail: [process: ProcessPlanItemVO]
|
||||
handleLeftoverMaterial: [process: ProcessPlanItemVO]
|
||||
}>()
|
||||
|
||||
const reportedQuantity = computed(() => props.process.reportedQuantity ?? 0)
|
||||
@ -160,6 +170,8 @@ const totalQty = computed(() => props.process.quantity ?? 0)
|
||||
const completedQty = computed(() => props.process.completedQty ?? 0)
|
||||
const scrapQty = computed(() => props.process.scrapQty ?? 0)
|
||||
const qualifiedQty = computed(() => Math.max(0, completedQty.value - scrapQty.value))
|
||||
const leftoverMaterials = computed(() => props.process.leftoverMaterials ?? 0) //剩余物料
|
||||
|
||||
|
||||
const progressPct = computed(() => {
|
||||
if (!totalQty.value) return 0
|
||||
@ -171,7 +183,7 @@ const passRate = computed(() => {
|
||||
return Math.round((qualifiedQty.value / completedQty.value) * 100)
|
||||
})
|
||||
|
||||
const remainQty = computed(() => Math.max(0, totalQty.value - completedQty.value))
|
||||
// const remainQty = computed(() => Math.max(0, totalQty.value - completedQty.value))
|
||||
|
||||
const statusTag = computed(() => {
|
||||
const s = props.process.processStatus
|
||||
@ -237,6 +249,22 @@ const planTimeText = computed(() => {
|
||||
}
|
||||
return start || end || '-'
|
||||
})
|
||||
|
||||
const refillDisAbled = ref<Boolean>(false);
|
||||
|
||||
async function geRefillRecord() {
|
||||
//查询补料记录
|
||||
const res = await refillRecordApi.getRefillNumByProcessId(props.process.planId);
|
||||
if (res >= props.process.scrapQty){
|
||||
refillDisAbled.value = true
|
||||
}
|
||||
refillDisAbled.value = false
|
||||
}
|
||||
|
||||
onMounted(()=>{
|
||||
geRefillRecord()
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@ -422,7 +422,12 @@ const columns: DataTableColumns<OrderProject> = [
|
||||
const buttons = []
|
||||
if (hasPermission('biz:orderProject:getKingdeeOrder')) {
|
||||
buttons.push(
|
||||
h(NButton, { size: 'small', quaternary: true, type: 'info', onClick: () => handleKingdeeQuery(row, false) }, {
|
||||
h(NButton, {
|
||||
size: 'small',
|
||||
quaternary: true,
|
||||
type: 'info',
|
||||
disabled: row.status != 1,
|
||||
onClick: () => handleKingdeeQuery(row, false) }, {
|
||||
default: () => [h(NIcon, null, { default: () => h(EyeOutline) }), ' 预生产查询']
|
||||
})
|
||||
)
|
||||
|
||||
@ -64,13 +64,26 @@
|
||||
:columns="columns"
|
||||
:data="tableData"
|
||||
:loading="loading"
|
||||
:pagination="pagination"
|
||||
:row-key="(row) => row.id!"
|
||||
:scroll-x="1680"
|
||||
/>
|
||||
<div class="pagination-container" style="display: flex; justify-content: flex-end; margin-top: 12px">
|
||||
<n-pagination
|
||||
v-model:page="pagination.page"
|
||||
v-model:page-size="pagination.pageSize"
|
||||
:item-count="pagination.itemCount"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
show-size-picker
|
||||
show-quick-jumper
|
||||
@update:page="handlePageChange"
|
||||
@update:page-size="handlePageSizeChange"
|
||||
@update:checked-row-keys="handleCheck"
|
||||
/>
|
||||
>
|
||||
<template #prefix>
|
||||
共 {{ pagination.itemCount }} 条
|
||||
</template>
|
||||
</n-pagination>
|
||||
</div>
|
||||
</n-card>
|
||||
|
||||
<!-- 详情 -->
|
||||
|
||||
@ -408,7 +408,7 @@ const AssingWorkDetailColums:DataTableColumns<AssingWorkDetail> = [
|
||||
},
|
||||
{
|
||||
align:'center',
|
||||
title: '质检状态',
|
||||
title: '状态',
|
||||
key: 'status',
|
||||
width: 100,
|
||||
render(row:any) {
|
||||
|
||||
@ -125,15 +125,6 @@ const reportRecordsColums:DataTableColumns<QualityTesting> = [
|
||||
)
|
||||
}
|
||||
},
|
||||
{ title: '来源类型', key: 'sourceType',align: 'center',
|
||||
render(row) {
|
||||
const val = row.sourceType
|
||||
const opt = qcSourceTypeOptions.value.find(o => o.value === val || String(o.value) === String(val))
|
||||
if (!opt) return val ?? '-'
|
||||
|
||||
return h(NTag, { type: opt.class, size: 'small' }, { default: () => opt.label })
|
||||
}
|
||||
},
|
||||
{ title: '报检总数', key: 'totalQty',align: 'center' },
|
||||
{ title: '已检验数量', key: 'inspectQty',align: 'center' },
|
||||
{ title: '质检状态', key: 'status',align: 'center',
|
||||
|
||||
@ -80,7 +80,7 @@ const reportRecordsColums:DataTableColumns<SubmitLog> = [
|
||||
{ title: '合格数量', key: 'qualifiedQty',align: 'center'},
|
||||
{ title: '报废数量', key: 'scrapQty',align: 'center'},
|
||||
{ title: '汇报人', key: 'userName',align: 'center' },
|
||||
{ title: '派工状态', key: 'submitStatus',align: 'center',
|
||||
{ title: '状态', key: 'submitStatus',align: 'center',
|
||||
render: (row) => {
|
||||
const val = row.submitStatus
|
||||
const opt = submitStatusOptions.value.find(o => o.value === val || String(o.value) === String(val))
|
||||
|
||||
Loading…
Reference in New Issue
Block a user