liuhairui il y a 2 semaines
Parent
commit
0eeb62b95a

+ 13 - 0
src/api/mes/job.js

@@ -1691,6 +1691,19 @@ export const sortProcess = (data) => {
   })
 }
 
+
+//工序产量核查
+export const checkProcessProduction = (params) => {
+  return service({
+    url: '/mes_server/work_order_process/checkProcessProduction',
+    method: 'get',
+    params,
+    donNotShowError: true,
+  })
+}
+
+
+
 /*设备工分报工产量跟踪*/
 
 //报工工分数据表左侧菜单栏

+ 31 - 0
src/utils/processProductionDialog.js

@@ -0,0 +1,31 @@
+import { ElMessage } from 'element-plus'
+import { checkProcessProduction } from '@/api/mes/job'
+
+/**
+ * 打开工序产量核查弹窗前预检:无报工数据则不打开弹窗,仅提示
+ * @returns {Promise<{ ok: boolean, workorder?: string }>}
+ */
+export async function ensureProcessProductionData(workorder) {
+  const w = String(workorder || '').trim()
+  if (!w) {
+    return { ok: false }
+  }
+
+  try {
+    const res = await checkProcessProduction({ workorder: w })
+    if (res?.code !== 0) {
+      ElMessage.warning(res?.msg || '未找到报工数据')
+      return { ok: false }
+    }
+    const list = res.data?.工序列表
+    if (!Array.isArray(list) || list.length === 0) {
+      ElMessage.warning('未找到报工数据')
+      return { ok: false }
+    }
+    return { ok: true, workorder: w }
+  } catch (error) {
+    console.error(error)
+    ElMessage.error('查询失败,请稍后重试')
+    return { ok: false }
+  }
+}

+ 331 - 0
src/view/SalaryManage/ProcessProduction.vue

@@ -0,0 +1,331 @@
+<template>
+  <div class="process-production-page" :class="{ 'in-dialog': inDialog }">
+    <div class="process-production-inner">
+      <el-form class="process-production-search" inline @keyup.enter="handleSearch">
+          <el-input
+            v-model="searchForm.workorder"
+            placeholder="请输入订单编号"
+            clearable
+            style="width: 200px"
+          />
+          <el-button type="primary" icon="search" :loading="loading" @click="handleSearch">
+            查询
+          </el-button>
+      </el-form>
+
+      <el-alert
+        v-if="pageHint"
+        class="process-production-hint"
+        :title="pageHint"
+        type="warning"
+        show-icon
+        :closable="false"
+      />
+
+      <el-descriptions class="order-summary-desc" :column="3" border>
+        <el-descriptions-item label="订单编号">
+          {{ orderSummary.订单编号 }}
+        </el-descriptions-item>
+        <el-descriptions-item label="生产款号">
+          {{ orderSummary.生产款号 }}
+        </el-descriptions-item>
+        <el-descriptions-item label="款式">
+          {{ orderSummary.款式 }}
+        </el-descriptions-item>
+      </el-descriptions>
+
+      <div class="process-production-table-wrap">
+        <el-table
+          v-loading="loading"
+          :data="displayTableData"
+          :height="tableHeight"
+          border
+          stripe
+          row-key="rowKey"
+          style="width: 100%"
+          :row-style="{ height: '32px' }"
+          :header-row-style="{ height: '36px' }"
+          :span-method="tableSpanMethod"
+          :summary-method="tableSummaryMethod"
+          show-summary
+          show-overflow-tooltip
+        >
+          <el-table-column label="工序编号" prop="工序号" width="100" align="center"  />
+          <el-table-column label="工序名称" prop="工序名称" min-width="280" align="left"  show-overflow-tooltip />
+          <el-table-column label="员工姓名" prop="员工姓名" width="100" align="left" />
+          <el-table-column label="完工数量" prop="数量" width="90" align="center" />
+          <el-table-column v-if="!hideAmountColumns" label="金额" prop="金额" width="90" align="center" />
+          <el-table-column v-if="!hideAmountColumns" label="工时" prop="工时" width="90" align="center" />
+          <el-table-column v-if="!hideAmountColumns" label="工资" prop="工资" width="90" align="center" />
+          <el-table-column label="开工日期" prop="开工日期" width="110" align="center" />
+          <el-table-column label="完工日期" prop="完工日期" width="110" align="center" />
+          <template #empty>
+            <el-empty
+              v-if="!loading"
+              :description="emptyDescription"
+              :image-size="100"
+            />
+          </template>
+        </el-table>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { computed, reactive, ref, watch } from 'vue'
+import { ElMessage } from 'element-plus'
+import { checkProcessProduction } from '@/api/mes/job'
+
+defineOptions({ name: 'ProcessProduction' })
+
+const props = defineProps({
+  /** 弹窗打开时传入的订单编号,会自动查询 */
+  initialWorkorder: { type: String, default: '' },
+  /** 嵌入订单资料弹窗时使用 */
+  inDialog: { type: Boolean, default: false },
+  /** 为 true 时不显示金额、工时、工资列(如样衣批核页) */
+  hideAmountColumns: { type: Boolean, default: false },
+})
+
+/** 主页面表格高度:改此值即可 */
+const MAIN_TABLE_HEIGHT = 'calc(100vh - 300px)'
+/** 弹窗内表格最大高度(距视口顶部的预留像素,含标题/搜索/订单信息栏) */
+const DIALOG_TABLE_OFFSET = 220
+const DIALOG_TABLE_EMPTY_HEIGHT = 320
+const TABLE_SUMMARY_ROW_HEIGHT = 40
+
+const sumTableColumn = (data, prop) => {
+  return data.reduce((sum, row) => {
+    const n = Number(row[prop])
+    return sum + (Number.isFinite(n) ? n : 0)
+  }, 0)
+}
+
+const formatSummaryValue = (total, prop) => {
+  if (!Number.isFinite(total)) return ''
+  if (prop === '数量') {
+    return Number.isInteger(total) ? String(total) : total.toFixed(2)
+  }
+  return total.toFixed(2)
+}
+
+const tableSummaryMethod = ({ columns, data }) => {
+  const summaryProps = props.hideAmountColumns
+    ? ['数量']
+    : ['数量', '金额', '工时', '工资']
+
+  return columns.map((column, index) => {
+    if (index === 0) return '合计'
+    const prop = column.property
+    if (!summaryProps.includes(prop)) return ''
+    return formatSummaryValue(sumTableColumn(data, prop), prop)
+  })
+}
+
+/** 弹窗按行数自适应高度,避免数据少时底部大块空白;主页面固定高度 */
+const tableHeight = computed(() => {
+  if (!props.inDialog) return MAIN_TABLE_HEIGHT
+  const rows = displayTableData.value.length
+  const maxH = Math.max(200, window.innerHeight - DIALOG_TABLE_OFFSET)
+  if (!rows) return Math.min(DIALOG_TABLE_EMPTY_HEIGHT, maxH)
+  const needH = rows * 32 + 36 + 12 + TABLE_SUMMARY_ROW_HEIGHT
+  return Math.min(Math.max(needH, 200), maxH)
+})
+
+const loading = ref(false)
+const searched = ref(false)
+/** 查询结果页内提示(如:未找到报工数据),不用 ElMessage 弹窗 */
+const pageHint = ref('')
+
+const emptyDescription = computed(() => {
+  if (!searched.value) return '请输入订单编号后查询'
+  return pageHint.value || '暂无数据'
+})
+
+const searchForm = reactive({
+  workorder: '',
+})
+
+const orderSummary = reactive({
+  订单编号: '',
+  生产款号: '',
+  款式: '',
+})
+
+const processListRaw = ref([])
+
+const flattenProcessList = (processList = []) => {
+  const rows = []
+  for (const proc of processList) {
+    const staffs = Array.isArray(proc.staffs) ? proc.staffs : []
+    if (!staffs.length) {
+      rows.push({
+        rowKey: `${proc.工序号}-empty`,
+        工序号: proc.工序号 ?? '',
+        工序名称: proc.工序名称 ?? '',
+        员工姓名: '',
+        数量: '',
+        开工日期: '',
+        完工日期: '',
+        金额: '',
+        工时: '',
+        工资: '',
+        _processRowSpan: 1,
+      })
+      continue
+    }
+    staffs.forEach((staff, index) => {
+      rows.push({
+        rowKey: `${proc.工序号}-${index}-${staff.员工姓名 || ''}`,
+        工序号: proc.工序号 ?? '',
+        工序名称: proc.工序名称 ?? '',
+        员工姓名: staff.员工姓名 ?? '',
+        数量: staff.数量 ?? '',
+        开工日期: staff.开工日期 ?? '',
+        完工日期: staff.完工日期 ?? '',
+        金额: staff.金额 ?? '',
+        工时: staff.工时 ?? '',
+        工资: staff.工资 ?? '',
+        _processRowSpan: index === 0 ? staffs.length : 0,
+      })
+    })
+  }
+  return rows
+}
+
+const displayTableData = computed(() => flattenProcessList(processListRaw.value || []))
+
+const tableSpanMethod = ({ row, column }) => {
+  if (column.property !== '工序号' && column.property !== '工序名称') {
+    return { rowspan: 1, colspan: 1 }
+  }
+  const rowspan = row._processRowSpan || 0
+  if (rowspan > 0) {
+    return { rowspan, colspan: 1 }
+  }
+  return { rowspan: 0, colspan: 0 }
+}
+
+const loadByWorkorder = async (workorder) => {
+  const w = String(workorder || '').trim()
+  if (!w) return
+  searchForm.workorder = w
+  await handleSearch()
+}
+
+const handleSearch = async () => {
+  const workorder = String(searchForm.workorder || '').trim()
+  if (!workorder) {
+    ElMessage.warning('请输入订单编号')
+    return
+  }
+
+  loading.value = true
+  searched.value = true
+  pageHint.value = ''
+  try {
+    const res = await checkProcessProduction({ workorder })
+    if (res?.code !== 0) {
+      processListRaw.value = []
+      orderSummary.订单编号 = workorder
+      orderSummary.生产款号 = ''
+      orderSummary.款式 = ''
+      pageHint.value = res?.msg || '未找到报工数据'
+      return
+    }
+
+    const data = res.data || {}
+    orderSummary.订单编号 = data.订单编号 || workorder
+    orderSummary.生产款号 = data.生产款号 || ''
+    orderSummary.款式 = data.款式 || ''
+    processListRaw.value = data.工序列表 || []
+    if (!processListRaw.value.length) {
+      pageHint.value = '未找到报工数据'
+    }
+  } catch (error) {
+    console.error(error)
+    pageHint.value = ''
+    ElMessage.error('查询失败,请稍后重试')
+    processListRaw.value = []
+  } finally {
+    loading.value = false
+  }
+}
+
+watch(
+  () => props.initialWorkorder,
+  (val) => {
+    if (val) loadByWorkorder(val)
+  },
+  { immediate: true }
+)
+
+defineExpose({ loadByWorkorder })
+</script>
+
+<style scoped>
+.process-production-page {
+  height: 100%;
+  background: transparent;
+}
+
+.process-production-page.in-dialog {
+  min-height: 0;
+}
+
+/* 主页面:右侧与左侧留白一致(左侧由布局已有间距,此处补右侧) */
+.process-production-page:not(.in-dialog) {
+  padding-right: 16px;
+  box-sizing: border-box;
+}
+
+.process-production-inner {
+  padding: 0 16px 12px;
+  box-sizing: border-box;
+  max-width: 100%;
+}
+
+.process-production-search {
+  margin-bottom: 8px;
+}
+
+.process-production-hint {
+  margin-bottom: 10px;
+}
+
+.process-production-search :deep(.el-form-item) {
+  margin-bottom: 0;
+  margin-right: 12px;
+}
+
+.order-summary-desc {
+  width: 100%;
+  margin-bottom: 10px;
+}
+
+.order-summary-desc :deep(.el-descriptions__label) {
+  width: 100px;
+  font-weight: normal;
+  color: #606266;
+  background: #f5f7fa;
+}
+
+.order-summary-desc :deep(.el-descriptions__content) {
+  color: #303133;
+}
+
+/* 不用 gva-table-box,避免全局白底卡片(main.scss: bg-white p-6 rounded) */
+.process-production-table-wrap {
+  width: 100%;
+  padding: 0;
+  background: transparent;
+  border-radius: 0;
+}
+
+.process-production-table-wrap :deep(.el-table__footer-wrapper td) {
+  font-weight: 600;
+  color: #303133;
+  background: #fafafa;
+}
+</style>

+ 96 - 1
src/view/yunyin/shengchanguanli/dahuobaobiao.vue

@@ -12,6 +12,7 @@
           />
           <el-button type="primary" icon="search" @click="onSearch">查询</el-button>
           <el-button type="primary" icon="download" @click="exportMonthlyData">导出出货大货生产进度表</el-button>
+          <el-button type="primary" icon="search" :loading="processProductionChecking" :disabled="!selectedOrderNo" @click="openProcessProductionDialog">工序产量核查</el-button>
         </div>
       </layout-header>
 
@@ -141,6 +142,37 @@
         </layout-content>
       </layout>
     </layout>
+
+    <!-- 工序产量核查 -->
+    <el-dialog
+      v-model="processProductionVisible"
+      width="100%"
+      style="height: 100%; margin: 0"
+      top="2vh"
+      :close-on-click-modal="true"
+      :show-close="false"
+      destroy-on-close
+      class="process-production-dialog"
+    >
+      <template #header>
+        <div class="process-production-dialog-header">
+          <span class="process-production-dialog-title">工序产量核查</span>
+          <el-button
+            type="danger"
+            size="small"
+            class="process-production-dialog-close"
+            @click="processProductionVisible = false"
+          >
+            关闭
+          </el-button>
+        </div>
+      </template>
+      <ProcessProduction
+        :key="processProductionDialogKey"
+        :initial-workorder="processProductionWorkorder"
+        in-dialog
+      />
+    </el-dialog>
   </div>
 </template>
   <script setup>
@@ -154,6 +186,8 @@
 
 
   import { ElMessage } from 'element-plus'
+  import ProcessProduction from '@/view/SalaryManage/ProcessProduction.vue'
+  import { ensureProcessProductionData } from '@/utils/processProductionDialog'
   import { useUserStore } from '@/pinia/modules/user'
   import * as ExcelJS from 'exceljs'
   import { saveAs } from 'file-saver'
@@ -568,6 +602,31 @@
   const fabricPlanDialogVisible = ref(false);
   const selectedOrder = ref({});
   const fabricPlanData = ref([]);
+
+  const selectedOrderNo = computed(() => String(selectedOrder.value?.订单编号 || '').trim())
+
+  const processProductionVisible = ref(false)
+  const processProductionWorkorder = ref('')
+  const processProductionDialogKey = ref(0)
+  const processProductionChecking = ref(false)
+
+  const openProcessProductionDialog = async () => {
+    const orderNo = selectedOrderNo.value
+    if (!orderNo) {
+      ElMessage.warning('请先在表格中点击选择订单')
+      return
+    }
+    processProductionChecking.value = true
+    try {
+      const result = await ensureProcessProductionData(orderNo)
+      if (!result.ok) return
+      processProductionWorkorder.value = result.workorder
+      processProductionDialogKey.value += 1
+      processProductionVisible.value = true
+    } finally {
+      processProductionChecking.value = false
+    }
+  }
   
   // 获取今天的日期,格式为 YYYY-MM-DD
   const getTodayYmd = () => {
@@ -1045,5 +1104,41 @@
     }
   }
   </style>
-  
+
+<style>
+  .process-production-dialog .el-dialog__header {
+    display: block;
+    width: 100%;
+    margin-right: 0;
+    padding: 16px 20px 12px;
+    box-sizing: border-box;
+  }
+
+  .process-production-dialog .el-dialog__body {
+    padding: 0;
+    background: #fff;
+  }
+
+  .process-production-dialog-header {
+    display: flex;
+    align-items: center;
+    width: 100%;
+    box-sizing: border-box;
+  }
+
+  .process-production-dialog-title {
+    flex: 1;
+    font-size: 16px;
+    font-weight: 600;
+    color: #303133;
+  }
+
+  .process-production-dialog-close {
+    flex-shrink: 0;
+    margin-left: auto;
+    min-width: 56px;
+    font-weight: 500;
+  }
+</style>
+
   

Fichier diff supprimé car celui-ci est trop grand
+ 444 - 358
src/view/yunyin/shengchanguanli/gongdanziliao.vue


+ 105 - 7
src/view/yunyin/shengchanguanli/yangyipihe.vue

@@ -2,12 +2,13 @@
 	<div style="margin: 0px;">
 	  <layout>
 		<layout-header>
-			<el-form>
+			<el-form class="yangyipihe-search-form" @submit.prevent="onSubmit">
 			  <el-form-item>
-				<el-input v-model="searchInfo" placeholder="查询订单编号、生产款号" @keyup.enter="onSubmit()"  style="width: 220px;"></el-input>
-				<el-button type="primary" icon="search" @click="onSubmit" >查询</el-button>
-				<el-button type="primary" icon="edit"   @click="hptg_onClick" :disabled="table_Selection === false"  class="bt" title="核批通过">核批通过</el-button>
-				<el-button type="primary" icon="edit"   @click="ztgg_onClick" :disabled="table_Selection === false"  class="bt" title="状态更改">状态更改</el-button>
+				<el-input v-model="searchInfo" placeholder="查询订单编号、生产款号" clearable style="width: 220px;" />
+				<el-button type="primary" native-type="button" icon="search" @click="onSubmit">查询</el-button>
+				<el-button type="primary" native-type="button" icon="edit" @click="hptg_onClick" :disabled="table_Selection === false" class="bt" title="核批通过">核批通过</el-button>
+				<el-button type="primary" native-type="button" icon="edit" @click="ztgg_onClick" :disabled="table_Selection === false" class="bt" title="状态更改">状态更改</el-button>
+				<el-button type="primary" native-type="button" icon="search" :loading="processProductionChecking" @click="openProcessProductionDialog" :disabled="!_Gd_gdbh" class="bt" title="工序产量核查">工序产量核查</el-button>
 			  </el-form-item>
 				<el-tag type="danger" style="font-size: 14px;">
 					<span>附件状态带有 “ </span>
@@ -27,7 +28,7 @@
 							:header-cell-style="{ padding: '0px' }"
 							highlight-current-row="true"
 							:show-overflow-tooltip="true"
-							style="width: 100%;height: 65vh" border  :data="tableData1" :row-key="orderTableRowKey" @selection-change="handleSelectionChange">
+							style="width: 100%;height: 65vh" border  :data="tableData1" :row-key="orderTableRowKey" @row-click="tableRowClick" @selection-change="handleSelectionChange">
 						<el-table-column   align="center" type="selection" width="40"/>
 						<el-table-column   align="center" label="技术附件状态" prop="status"  width="110" />
 						<el-table-column   align="center" label="订单附件状态" prop="orderstatus"  width="110" />
@@ -105,6 +106,38 @@
 		</layout-content>
 		</layout>
 	  </layout>
+
+	  <!-- 工序产量核查 -->
+	  <el-dialog
+		v-model="processProductionVisible"
+		width="100%"
+		style="height: 100%; margin: 0"
+		top="2vh"
+		:close-on-click-modal="true"
+		:show-close="false"
+		destroy-on-close
+		class="process-production-dialog"
+	  >
+		<template #header>
+		  <div class="process-production-dialog-header">
+			<span class="process-production-dialog-title">工序产量核查</span>
+			<el-button
+			  type="danger"
+			  size="small"
+			  class="process-production-dialog-close"
+			  @click="processProductionVisible = false"
+			>
+			  关闭
+			</el-button>
+		  </div>
+		</template>
+		<ProcessProduction
+		  :key="processProductionDialogKey"
+		  :initial-workorder="processProductionWorkorder"
+		  in-dialog
+		  hide-amount-columns
+		/>
+	  </el-dialog>
 	</div>
   </template>
   <script setup>
@@ -114,6 +147,8 @@
   import {UnapprovalList, Approval, Apigdstatus} from '@/api/mes/job'
   import {ElMessage} from "element-plus";
   import { useUserStore } from '@/pinia/modules/user';
+  import ProcessProduction from '@/view/SalaryManage/ProcessProduction.vue'
+  import { ensureProcessProductionData } from '@/utils/processProductionDialog'
   
   defineOptions({name: 'Company'})
   
@@ -181,6 +216,34 @@
   const _Uniqid = ref('');  
   const multipleTable = ref(null);
   
+  const _Gd_gdbh = ref('')
+
+  const tableRowClick = (row) => {
+    _Gd_gdbh.value = row?.订单编号 || ''
+  }
+
+  const processProductionVisible = ref(false)
+  const processProductionWorkorder = ref('')
+  const processProductionDialogKey = ref(0)
+  const processProductionChecking = ref(false)
+
+  const openProcessProductionDialog = async () => {
+    if (!_Gd_gdbh.value) {
+      ElMessage.warning('请先在表格中点击选择订单')
+      return
+    }
+    processProductionChecking.value = true
+    try {
+      const result = await ensureProcessProductionData(_Gd_gdbh.value)
+      if (!result.ok) return
+      processProductionWorkorder.value = result.workorder
+      processProductionDialogKey.value += 1
+      processProductionVisible.value = true
+    } finally {
+      processProductionChecking.value = false
+    }
+  }
+
   const handleSelectionChange = (selection) => {
     if(selection.length >= 1) {
       table_Selection.value = true;
@@ -275,4 +338,39 @@
 	padding: 0px !important;
   }
   </style>
-  
+
+<style>
+  .process-production-dialog .el-dialog__header {
+    display: block;
+    width: 100%;
+    margin-right: 0;
+    padding: 16px 20px 12px;
+    box-sizing: border-box;
+  }
+
+  .process-production-dialog .el-dialog__body {
+    padding: 0;
+    background: #fff;
+  }
+
+  .process-production-dialog-header {
+    display: flex;
+    align-items: center;
+    width: 100%;
+    box-sizing: border-box;
+  }
+
+  .process-production-dialog-title {
+    flex: 1;
+    font-size: 16px;
+    font-weight: 600;
+    color: #303133;
+  }
+
+  .process-production-dialog-close {
+    flex-shrink: 0;
+    margin-left: auto;
+    min-width: 56px;
+    font-weight: 500;
+  }
+</style>

+ 1 - 1
src/view/yunyin/shengchanguanli/yuedudahuoshengchanjindu.vue

@@ -92,7 +92,7 @@
 // 全量引入格式化工具 请按需保留
 import { Layout, LayoutSider, LayoutContent } from '@arco-design/web-vue';
 import {ref, reactive} from 'vue'
-import {dateList,OrderYieldList,Datalist,ProductInformation} from '@/api/mes/job'
+import { OrderYieldList, ProductInformation } from '@/api/mes/job'
 import * as XLSX from 'xlsx'
 import FileSaver from 'file-saver'
 import {ElMessage} from "element-plus";

Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff