|
|
@@ -1,113 +1,202 @@
|
|
|
<template>
|
|
|
- <AidopDemoShell :title="pageTitle" subtitle="只读列表">
|
|
|
- <el-form :inline="true" :model="query" class="mb12" @submit.prevent>
|
|
|
- <el-form-item label="生产指令单">
|
|
|
- <el-input v-model="query.productionOrderNo" clearable style="width: 200px" />
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="生产批号">
|
|
|
- <el-input v-model="query.productionBatchNo" clearable style="width: 200px" />
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="物料编码">
|
|
|
- <el-input v-model="query.materialCode" clearable style="width: 200px" />
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="申请时间">
|
|
|
- <el-date-picker
|
|
|
- v-model="applyTimeRange"
|
|
|
- type="daterange"
|
|
|
- value-format="YYYY-MM-DD"
|
|
|
- range-separator="-"
|
|
|
- start-placeholder="开始日期"
|
|
|
- end-placeholder="结束日期"
|
|
|
- unlink-panels
|
|
|
- style="width: 260px"
|
|
|
- />
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="检验进度">
|
|
|
- <el-select v-model="query.inspectProgress" placeholder="全部" clearable style="width: 160px">
|
|
|
- <el-option label="未检验" value="未检验" />
|
|
|
- <el-option label="检验中" value="检验中" />
|
|
|
- <el-option label="检验完成" value="检验完成" />
|
|
|
- </el-select>
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="检验优先级">
|
|
|
- <el-input v-model="query.priority" clearable style="width: 160px" />
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="检验负责人">
|
|
|
- <el-input v-model="query.inspector" clearable style="width: 160px" />
|
|
|
- </el-form-item>
|
|
|
- <el-form-item>
|
|
|
- <el-button type="primary" @click="doSearch">查询</el-button>
|
|
|
- <el-button @click="resetQuery">重置</el-button>
|
|
|
- </el-form-item>
|
|
|
- </el-form>
|
|
|
-
|
|
|
- <!-- 本批只读:动作按钮保留占位但禁用,不接真实写动作 -->
|
|
|
- <div class="mb12 actions">
|
|
|
- <el-tooltip content="本批为只读列表,暂不开放" placement="top">
|
|
|
- <span><el-button disabled>检验完成</el-button></span>
|
|
|
- </el-tooltip>
|
|
|
- <el-tooltip content="本批为只读列表,暂不开放" placement="top">
|
|
|
- <span><el-button disabled>认领</el-button></span>
|
|
|
- </el-tooltip>
|
|
|
- <el-tooltip content="本批为只读列表,暂不开放" placement="top">
|
|
|
- <span><el-button disabled>检验员调配</el-button></span>
|
|
|
- </el-tooltip>
|
|
|
- <el-tooltip content="本批为只读列表,暂不开放" placement="top">
|
|
|
- <span><el-button disabled>优先级调整</el-button></span>
|
|
|
- </el-tooltip>
|
|
|
- </div>
|
|
|
-
|
|
|
- <el-table :data="rows" row-key="id" v-loading="loading" border stripe>
|
|
|
- <el-table-column prop="productionOrderNo" label="生产指令单" min-width="150" show-overflow-tooltip resizable />
|
|
|
- <el-table-column prop="applyTime" label="申请时间" min-width="170" resizable>
|
|
|
- <template #default="{ row }">{{ fmtDateTime(row.applyTime) }}</template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column prop="materialCode" label="物料编码" min-width="140" show-overflow-tooltip resizable />
|
|
|
- <el-table-column prop="productName" label="产品名称" min-width="160" show-overflow-tooltip resizable />
|
|
|
- <el-table-column prop="productModel" label="产品型号" min-width="140" show-overflow-tooltip resizable />
|
|
|
- <el-table-column prop="productionBatchNo" label="生产批号" min-width="140" show-overflow-tooltip resizable />
|
|
|
- <el-table-column prop="orderQty" label="指令单数量" min-width="120" resizable />
|
|
|
- <el-table-column prop="applicant" label="申请人" min-width="120" show-overflow-tooltip resizable />
|
|
|
- <el-table-column prop="remark" label="备注" min-width="160" show-overflow-tooltip resizable />
|
|
|
- <el-table-column prop="priority" label="检验优先级" min-width="110" resizable />
|
|
|
- <el-table-column prop="inspectStartTime" label="检验开始时间" min-width="170" resizable>
|
|
|
- <template #default="{ row }">{{ fmtDateTime(row.inspectStartTime) }}</template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column prop="inspectFinishTime" label="检验完成时间" min-width="170" resizable>
|
|
|
- <template #default="{ row }">{{ fmtDateTime(row.inspectFinishTime) }}</template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column prop="inspector" label="检验负责人" min-width="120" show-overflow-tooltip resizable />
|
|
|
- <el-table-column prop="inspectProgress" label="检验进度" min-width="110" resizable />
|
|
|
- <template #empty>
|
|
|
- <el-empty description="暂无数据" />
|
|
|
+ <AidopDemoShell :title="pageTitle" subtitle="认领 → 生成检验单 → 录入检验(提交转主管审核)">
|
|
|
+ <el-tabs v-model="activeTab" @tab-change="onTabChange">
|
|
|
+ <!-- ===== 待检任务 ===== -->
|
|
|
+ <el-tab-pane label="待检任务" name="entry">
|
|
|
+ <el-form :inline="true" :model="entryQuery" class="mb12" @submit.prevent>
|
|
|
+ <el-form-item label="生产指令单"><el-input v-model="entryQuery.productionOrderNo" clearable style="width: 180px" /></el-form-item>
|
|
|
+ <el-form-item label="生产批号"><el-input v-model="entryQuery.productionBatchNo" clearable style="width: 160px" /></el-form-item>
|
|
|
+ <el-form-item label="物料编码"><el-input v-model="entryQuery.materialCode" clearable style="width: 160px" /></el-form-item>
|
|
|
+ <el-form-item label="申请时间">
|
|
|
+ <el-date-picker v-model="applyTimeRange" type="daterange" value-format="YYYY-MM-DD" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" unlink-panels style="width: 260px" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="检验进度">
|
|
|
+ <el-select v-model="entryQuery.inspectProgress" placeholder="全部" clearable style="width: 140px">
|
|
|
+ <el-option label="未检验" value="未检验" />
|
|
|
+ <el-option label="检验中" value="检验中" />
|
|
|
+ <el-option label="检验完成" value="检验完成" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="检验优先级">
|
|
|
+ <el-select v-model="entryQuery.priority" placeholder="全部" clearable style="width: 120px">
|
|
|
+ <el-option label="正常" value="正常" />
|
|
|
+ <el-option label="紧急" value="紧急" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="检验负责人"><el-input v-model="entryQuery.inspector" clearable style="width: 140px" /></el-form-item>
|
|
|
+ <el-form-item>
|
|
|
+ <el-button type="primary" @click="doEntrySearch">查询</el-button>
|
|
|
+ <el-button @click="resetEntryQuery">重置</el-button>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+
|
|
|
+ <div class="mb12 actions">
|
|
|
+ <el-button type="primary" :disabled="!selectedEntryIds.length" @click="onClaim">认领</el-button>
|
|
|
+ <el-button :disabled="!selectedEntryIds.length" @click="openAssign">检验员调配</el-button>
|
|
|
+ <el-button :disabled="!selectedEntryIds.length" @click="openPriority">优先级调整</el-button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <el-table :data="entryRows" row-key="id" v-loading="entryLoading" border stripe @selection-change="onEntrySelection">
|
|
|
+ <el-table-column type="selection" width="48" />
|
|
|
+ <el-table-column prop="applyBillNo" label="报检单号" min-width="160" show-overflow-tooltip resizable />
|
|
|
+ <el-table-column prop="productionOrderNo" label="生产指令单" min-width="130" show-overflow-tooltip resizable />
|
|
|
+ <el-table-column prop="materialCode" label="物料编码" min-width="120" show-overflow-tooltip resizable />
|
|
|
+ <el-table-column prop="productName" label="产品名称" min-width="150" show-overflow-tooltip resizable />
|
|
|
+ <el-table-column prop="productModel" label="产品型号" min-width="120" show-overflow-tooltip resizable />
|
|
|
+ <el-table-column prop="productionBatchNo" label="生产批号" min-width="120" show-overflow-tooltip resizable />
|
|
|
+ <el-table-column prop="orderQty" label="指令单数量" min-width="100" align="right" resizable />
|
|
|
+ <el-table-column prop="applyQty" label="报检数量" min-width="90" align="right" resizable />
|
|
|
+ <el-table-column prop="priority" label="检验优先级" min-width="100" resizable>
|
|
|
+ <template #default="{ row }">
|
|
|
+ <el-tag v-if="row.priority === '紧急'" type="danger" size="small">紧急</el-tag>
|
|
|
+ <el-tag v-else-if="row.priority === '正常'" type="info" size="small">正常</el-tag>
|
|
|
+ <span v-else>{{ row.priority || '' }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="ownerName" label="检验负责人" min-width="110" show-overflow-tooltip resizable>
|
|
|
+ <template #default="{ row }">{{ row.ownerName || '' }}</template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="applicant" label="申请人" min-width="100" show-overflow-tooltip resizable />
|
|
|
+ <el-table-column prop="applyTime" label="申请时间" min-width="160" resizable>
|
|
|
+ <template #default="{ row }">{{ fmtDateTime(row.applyTime) }}</template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="inspectStartTime" label="检验开始时间" min-width="160" resizable>
|
|
|
+ <template #default="{ row }">{{ fmtDateTime(row.inspectStartTime) }}</template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="inspectProgress" label="检验进度" min-width="100" resizable />
|
|
|
+ <el-table-column prop="inspBillNo" label="检验单号" min-width="150" show-overflow-tooltip resizable />
|
|
|
+ <el-table-column label="操作" width="130" fixed="right">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <el-button v-if="!row.inspBillId" type="success" link :loading="generatingId === row.id" @click="onGenerate(row)">生成检验单</el-button>
|
|
|
+ <el-button v-else type="warning" link @click="openInspection(row)">录入检验</el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <template #empty><el-empty description="暂无待检任务" /></template>
|
|
|
+ </el-table>
|
|
|
+
|
|
|
+ <div class="pager">
|
|
|
+ <el-pagination v-model:current-page="entryQuery.page" v-model:page-size="entryQuery.pageSize" :total="entryTotal" :page-sizes="[10, 20, 50]" layout="total, sizes, prev, pager, next" @current-change="loadEntryList" @size-change="loadEntryList" />
|
|
|
+ </div>
|
|
|
+ </el-tab-pane>
|
|
|
+
|
|
|
+ <!-- ===== 检验单 ===== -->
|
|
|
+ <el-tab-pane label="检验单" name="bill">
|
|
|
+ <el-form :inline="true" :model="billQuery" class="mb12" @submit.prevent>
|
|
|
+ <el-form-item label="单据编号"><el-input v-model="billQuery.billNo" clearable style="width: 180px" /></el-form-item>
|
|
|
+ <el-form-item label="生产批号"><el-input v-model="billQuery.productionBatchNo" clearable style="width: 160px" /></el-form-item>
|
|
|
+ <el-form-item label="生产指令单"><el-input v-model="billQuery.productionOrderNo" clearable style="width: 160px" /></el-form-item>
|
|
|
+ <el-form-item label="物料编码"><el-input v-model="billQuery.materialCode" clearable style="width: 160px" /></el-form-item>
|
|
|
+ <el-form-item>
|
|
|
+ <el-button type="primary" @click="doBillSearch">查询</el-button>
|
|
|
+ <el-button @click="resetBillQuery">重置</el-button>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+
|
|
|
+ <el-table :data="billRows" row-key="id" v-loading="billLoading" border stripe>
|
|
|
+ <el-table-column prop="billNo" label="单据编号" min-width="150" show-overflow-tooltip resizable />
|
|
|
+ <el-table-column prop="inspectTime" label="检验时间" min-width="160" resizable>
|
|
|
+ <template #default="{ row }">{{ fmtDateTime(row.inspectTime) }}</template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="productionBatchNo" label="生产批号" min-width="130" show-overflow-tooltip resizable />
|
|
|
+ <el-table-column prop="materialCode" label="物料编码" min-width="130" show-overflow-tooltip resizable />
|
|
|
+ <el-table-column prop="materialName" label="物料名称" min-width="150" show-overflow-tooltip resizable />
|
|
|
+ <el-table-column prop="spec" label="规格型号" min-width="130" show-overflow-tooltip resizable />
|
|
|
+ <el-table-column prop="sourceBillNo" label="来源单据编号" min-width="150" show-overflow-tooltip resizable />
|
|
|
+ <el-table-column prop="productionOrderNo" label="生产指令单" min-width="130" show-overflow-tooltip resizable />
|
|
|
+ <el-table-column prop="judgment" label="判定" min-width="90" resizable />
|
|
|
+ <el-table-column prop="qualifiedQty" label="合格数量" min-width="100" align="right" resizable />
|
|
|
+ <el-table-column prop="unqualifiedQty" label="不合格数量" min-width="110" align="right" resizable />
|
|
|
+ <el-table-column label="操作" width="90" fixed="right">
|
|
|
+ <template #default="{ row }"><el-button link type="primary" @click="openDetail(row)">查看</el-button></template>
|
|
|
+ </el-table-column>
|
|
|
+ <template #empty><el-empty description="暂无检验单" /></template>
|
|
|
+ </el-table>
|
|
|
+
|
|
|
+ <div class="pager">
|
|
|
+ <el-pagination v-model:current-page="billQuery.page" v-model:page-size="billQuery.pageSize" :total="billTotal" :page-sizes="[10, 20, 50]" layout="total, sizes, prev, pager, next" @current-change="loadBillList" @size-change="loadBillList" />
|
|
|
+ </div>
|
|
|
+ </el-tab-pane>
|
|
|
+ </el-tabs>
|
|
|
+
|
|
|
+ <FqcInspBillDetailDrawer
|
|
|
+ v-model="detailVisible"
|
|
|
+ :detail="detail"
|
|
|
+ :loading="detailLoading"
|
|
|
+ :flow-state="flowState"
|
|
|
+ :submitting="flowSubmitting"
|
|
|
+ @submit-result="onFlowSubmit"
|
|
|
+ @approve="onFlowApprove"
|
|
|
+ @reject="onFlowReject"
|
|
|
+ @qe-submit="onFlowQe"
|
|
|
+ />
|
|
|
+
|
|
|
+ <el-dialog v-model="assignVisible" title="检验员调配" width="420px">
|
|
|
+ <el-form label-width="100px">
|
|
|
+ <el-form-item label="用户 Id"><el-input v-model="assignUserId" placeholder="填写检验员用户 Id" /></el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <template #footer>
|
|
|
+ <el-button @click="assignVisible = false">取消</el-button>
|
|
|
+ <el-button type="primary" @click="onAssign">确定</el-button>
|
|
|
</template>
|
|
|
- </el-table>
|
|
|
-
|
|
|
- <div class="pager">
|
|
|
- <el-pagination
|
|
|
- v-model:current-page="query.page"
|
|
|
- v-model:page-size="query.pageSize"
|
|
|
- :total="total"
|
|
|
- :page-sizes="[10, 20, 50]"
|
|
|
- layout="total, sizes, prev, pager, next"
|
|
|
- @current-change="loadList"
|
|
|
- @size-change="loadList"
|
|
|
- />
|
|
|
- </div>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <el-dialog v-model="priorityVisible" title="优先级调整" width="420px">
|
|
|
+ <el-form label-width="100px">
|
|
|
+ <el-form-item label="优先级">
|
|
|
+ <el-select v-model="priorityValue" style="width: 160px">
|
|
|
+ <el-option label="正常" value="正常" />
|
|
|
+ <el-option label="紧急" value="紧急" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <template #footer>
|
|
|
+ <el-button @click="priorityVisible = false">取消</el-button>
|
|
|
+ <el-button type="primary" @click="onPriority">确定</el-button>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
</AidopDemoShell>
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts" name="aidopS7FqcTaskList">
|
|
|
import { computed, onActivated, onMounted, reactive, ref } from 'vue';
|
|
|
-import { useRoute } from 'vue-router';
|
|
|
+import { useRoute, useRouter } from 'vue-router';
|
|
|
import { ElMessage } from 'element-plus';
|
|
|
import AidopDemoShell from '/@/views/aidop/components/AidopDemoShell.vue';
|
|
|
-import { fetchFqcTaskList, type FqcTaskRow } from '../api/fqcInspBill';
|
|
|
+import FqcInspBillDetailDrawer from './components/FqcInspBillDetailDrawer.vue';
|
|
|
+import { fetchFqcResultList, fetchFqcDetail, type FqcResultRow, type FqcDetail } from '../api/fqcInspBill';
|
|
|
+import {
|
|
|
+ fetchFqcTaskEntryList,
|
|
|
+ claimFqcTaskEntries,
|
|
|
+ assignFqcTaskEntries,
|
|
|
+ adjustFqcTaskPriority,
|
|
|
+ generateFqcInspBillByTask,
|
|
|
+ type FqcTaskEntryRow,
|
|
|
+} from '../api/fqcTaskEntry';
|
|
|
+import {
|
|
|
+ fetchFqcFlowState,
|
|
|
+ submitFqcResult,
|
|
|
+ fqcSupervisorApprove,
|
|
|
+ fqcSupervisorReject,
|
|
|
+ submitFqcQeDisposition,
|
|
|
+ type FqcFlowState,
|
|
|
+ type FqcSubmitResultPayload,
|
|
|
+ type FqcQeDispositionPayload,
|
|
|
+} from '../api/fqcInspBillFlow';
|
|
|
|
|
|
const route = useRoute();
|
|
|
+const router = useRouter();
|
|
|
const pageTitle = computed(() => (route.meta?.title as string) || 'FQC检验任务列表');
|
|
|
|
|
|
-const query = reactive({
|
|
|
+const activeTab = ref('entry');
|
|
|
+
|
|
|
+function fmtDateTime(v?: string | null) {
|
|
|
+ if (!v) return '';
|
|
|
+ const s = String(v);
|
|
|
+ return s.length > 19 ? s.slice(0, 19).replace('T', ' ') : s.replace('T', ' ');
|
|
|
+}
|
|
|
+
|
|
|
+// ── 待检任务 ──
|
|
|
+const entryQuery = reactive({
|
|
|
productionOrderNo: '',
|
|
|
productionBatchNo: '',
|
|
|
materialCode: '',
|
|
|
@@ -119,68 +208,250 @@ const query = reactive({
|
|
|
page: 1,
|
|
|
pageSize: 10,
|
|
|
});
|
|
|
-
|
|
|
const applyTimeRange = ref<[string, string] | null>(null);
|
|
|
+const entryLoading = ref(false);
|
|
|
+const entryRows = ref<FqcTaskEntryRow[]>([]);
|
|
|
+const entryTotal = ref(0);
|
|
|
+const selectedEntryIds = ref<number[]>([]);
|
|
|
+const generatingId = ref<number | null>(null);
|
|
|
|
|
|
-const loading = ref(false);
|
|
|
-const rows = ref<FqcTaskRow[]>([]);
|
|
|
-const total = ref(0);
|
|
|
+const assignVisible = ref(false);
|
|
|
+const assignUserId = ref('');
|
|
|
+const priorityVisible = ref(false);
|
|
|
+const priorityValue = ref<'正常' | '紧急'>('正常');
|
|
|
|
|
|
-function fmtDateTime(v?: string | null) {
|
|
|
- if (!v) return '';
|
|
|
- const s = String(v);
|
|
|
- return s.length > 19 ? s.slice(0, 19).replace('T', ' ') : s.replace('T', ' ');
|
|
|
+function onEntrySelection(rowsSel: FqcTaskEntryRow[]) {
|
|
|
+ selectedEntryIds.value = rowsSel.map((r) => Number(r.id)).filter((x) => x > 0);
|
|
|
}
|
|
|
|
|
|
-async function loadList() {
|
|
|
- loading.value = true;
|
|
|
+async function loadEntryList() {
|
|
|
+ entryLoading.value = true;
|
|
|
try {
|
|
|
- query.applyTimeStart = applyTimeRange.value?.[0] || '';
|
|
|
- query.applyTimeEnd = applyTimeRange.value?.[1] || '';
|
|
|
- const data = await fetchFqcTaskList({
|
|
|
- productionOrderNo: query.productionOrderNo,
|
|
|
- productionBatchNo: query.productionBatchNo,
|
|
|
- materialCode: query.materialCode,
|
|
|
- applyTimeStart: query.applyTimeStart,
|
|
|
- applyTimeEnd: query.applyTimeEnd,
|
|
|
- inspectProgress: query.inspectProgress,
|
|
|
- priority: query.priority,
|
|
|
- inspector: query.inspector,
|
|
|
- page: query.page,
|
|
|
- pageSize: query.pageSize,
|
|
|
- });
|
|
|
- rows.value = data.list || [];
|
|
|
- total.value = data.total || 0;
|
|
|
+ entryQuery.applyTimeStart = applyTimeRange.value?.[0] || '';
|
|
|
+ entryQuery.applyTimeEnd = applyTimeRange.value?.[1] || '';
|
|
|
+ const data = await fetchFqcTaskEntryList({ ...entryQuery });
|
|
|
+ entryRows.value = data.list || [];
|
|
|
+ entryTotal.value = data.total || 0;
|
|
|
} catch (e: any) {
|
|
|
- rows.value = [];
|
|
|
- total.value = 0;
|
|
|
- ElMessage.error(e?.message || '加载FQC检验任务列表失败');
|
|
|
+ entryRows.value = [];
|
|
|
+ entryTotal.value = 0;
|
|
|
+ ElMessage.error(e?.message || '加载待检任务失败');
|
|
|
} finally {
|
|
|
- loading.value = false;
|
|
|
+ entryLoading.value = false;
|
|
|
}
|
|
|
}
|
|
|
+function doEntrySearch() {
|
|
|
+ entryQuery.page = 1;
|
|
|
+ loadEntryList();
|
|
|
+}
|
|
|
+function resetEntryQuery() {
|
|
|
+ entryQuery.productionOrderNo = '';
|
|
|
+ entryQuery.productionBatchNo = '';
|
|
|
+ entryQuery.materialCode = '';
|
|
|
+ applyTimeRange.value = null;
|
|
|
+ entryQuery.applyTimeStart = '';
|
|
|
+ entryQuery.applyTimeEnd = '';
|
|
|
+ entryQuery.inspectProgress = '';
|
|
|
+ entryQuery.priority = '';
|
|
|
+ entryQuery.inspector = '';
|
|
|
+ entryQuery.page = 1;
|
|
|
+ loadEntryList();
|
|
|
+}
|
|
|
|
|
|
-function doSearch() {
|
|
|
- query.page = 1;
|
|
|
- loadList();
|
|
|
+async function onClaim() {
|
|
|
+ try {
|
|
|
+ await claimFqcTaskEntries(selectedEntryIds.value);
|
|
|
+ ElMessage.success('认领成功');
|
|
|
+ loadEntryList();
|
|
|
+ } catch (e: any) {
|
|
|
+ ElMessage.error(e?.message || '认领失败');
|
|
|
+ }
|
|
|
+}
|
|
|
+function openAssign() {
|
|
|
+ assignUserId.value = '';
|
|
|
+ assignVisible.value = true;
|
|
|
+}
|
|
|
+async function onAssign() {
|
|
|
+ const uid = Number(assignUserId.value);
|
|
|
+ if (!uid) {
|
|
|
+ ElMessage.warning('请填写有效的用户 Id');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ await assignFqcTaskEntries(selectedEntryIds.value, uid);
|
|
|
+ ElMessage.success('调配成功');
|
|
|
+ assignVisible.value = false;
|
|
|
+ loadEntryList();
|
|
|
+ } catch (e: any) {
|
|
|
+ ElMessage.error(e?.message || '调配失败');
|
|
|
+ }
|
|
|
+}
|
|
|
+function openPriority() {
|
|
|
+ priorityValue.value = '正常';
|
|
|
+ priorityVisible.value = true;
|
|
|
+}
|
|
|
+async function onPriority() {
|
|
|
+ try {
|
|
|
+ await adjustFqcTaskPriority(selectedEntryIds.value, priorityValue.value);
|
|
|
+ ElMessage.success('优先级已更新');
|
|
|
+ priorityVisible.value = false;
|
|
|
+ loadEntryList();
|
|
|
+ } catch (e: any) {
|
|
|
+ ElMessage.error(e?.message || '调整失败');
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-function resetQuery() {
|
|
|
- query.productionOrderNo = '';
|
|
|
- query.productionBatchNo = '';
|
|
|
- query.materialCode = '';
|
|
|
- applyTimeRange.value = null;
|
|
|
- query.applyTimeStart = '';
|
|
|
- query.applyTimeEnd = '';
|
|
|
- query.inspectProgress = '';
|
|
|
- query.priority = '';
|
|
|
- query.inspector = '';
|
|
|
- query.page = 1;
|
|
|
- loadList();
|
|
|
+async function onGenerate(row: FqcTaskEntryRow) {
|
|
|
+ if (!row?.id || generatingId.value) return;
|
|
|
+ generatingId.value = row.id;
|
|
|
+ try {
|
|
|
+ const res = await generateFqcInspBillByTask(row.id);
|
|
|
+ ElMessage.success(`已生成检验单 ${res.inspBillNo}`);
|
|
|
+ await loadEntryList();
|
|
|
+ if (res.inspBillId) router.push({ path: '/aidop/s7/fqc/insp-detail', query: { id: String(res.inspBillId) } });
|
|
|
+ } catch (e: any) {
|
|
|
+ ElMessage.error(e?.message || '生成检验单失败');
|
|
|
+ } finally {
|
|
|
+ generatingId.value = null;
|
|
|
+ }
|
|
|
+}
|
|
|
+function openInspection(row: FqcTaskEntryRow) {
|
|
|
+ if (!row.inspBillId) return;
|
|
|
+ router.push({ path: '/aidop/s7/fqc/insp-detail', query: { id: String(row.inspBillId) } });
|
|
|
+}
|
|
|
+
|
|
|
+// ── 检验单 ──
|
|
|
+const billQuery = reactive({ billNo: '', productionBatchNo: '', productionOrderNo: '', materialCode: '', page: 1, pageSize: 10 });
|
|
|
+const billLoading = ref(false);
|
|
|
+const billRows = ref<FqcResultRow[]>([]);
|
|
|
+const billTotal = ref(0);
|
|
|
+
|
|
|
+async function loadBillList() {
|
|
|
+ billLoading.value = true;
|
|
|
+ try {
|
|
|
+ const data = await fetchFqcResultList({ ...billQuery });
|
|
|
+ billRows.value = data.list || [];
|
|
|
+ billTotal.value = data.total || 0;
|
|
|
+ } catch (e: any) {
|
|
|
+ billRows.value = [];
|
|
|
+ billTotal.value = 0;
|
|
|
+ ElMessage.error(e?.message || '加载FQC检验单列表失败');
|
|
|
+ } finally {
|
|
|
+ billLoading.value = false;
|
|
|
+ }
|
|
|
+}
|
|
|
+function doBillSearch() {
|
|
|
+ billQuery.page = 1;
|
|
|
+ loadBillList();
|
|
|
+}
|
|
|
+function resetBillQuery() {
|
|
|
+ billQuery.billNo = '';
|
|
|
+ billQuery.productionBatchNo = '';
|
|
|
+ billQuery.productionOrderNo = '';
|
|
|
+ billQuery.materialCode = '';
|
|
|
+ billQuery.page = 1;
|
|
|
+ loadBillList();
|
|
|
}
|
|
|
|
|
|
-onMounted(() => loadList());
|
|
|
-onActivated(() => loadList());
|
|
|
+// ── 检验单详情 + 流程 ──
|
|
|
+const detailVisible = ref(false);
|
|
|
+const detail = ref<FqcDetail | null>(null);
|
|
|
+const detailLoading = ref(false);
|
|
|
+const flowState = ref<FqcFlowState | null>(null);
|
|
|
+const flowSubmitting = ref(false);
|
|
|
+const currentDetailId = ref<number | null>(null);
|
|
|
+
|
|
|
+async function loadDetailAndState(id: number) {
|
|
|
+ detailLoading.value = true;
|
|
|
+ try {
|
|
|
+ const [d, s] = await Promise.all([fetchFqcDetail(id), fetchFqcFlowState(id)]);
|
|
|
+ detail.value = d;
|
|
|
+ flowState.value = s;
|
|
|
+ } catch (e: any) {
|
|
|
+ detail.value = null;
|
|
|
+ flowState.value = null;
|
|
|
+ ElMessage.error(e?.message || '加载FQC检验单详情失败');
|
|
|
+ } finally {
|
|
|
+ detailLoading.value = false;
|
|
|
+ }
|
|
|
+}
|
|
|
+async function openDetail(row: FqcResultRow) {
|
|
|
+ if (!row?.id) return;
|
|
|
+ currentDetailId.value = row.id;
|
|
|
+ detail.value = null;
|
|
|
+ flowState.value = null;
|
|
|
+ detailVisible.value = true;
|
|
|
+ await loadDetailAndState(row.id);
|
|
|
+}
|
|
|
+async function onFlowSubmit(payload: FqcSubmitResultPayload) {
|
|
|
+ flowSubmitting.value = true;
|
|
|
+ try {
|
|
|
+ await submitFqcResult(payload);
|
|
|
+ ElMessage.success('检验结果已提交');
|
|
|
+ if (currentDetailId.value) await loadDetailAndState(currentDetailId.value);
|
|
|
+ loadBillList();
|
|
|
+ loadEntryList();
|
|
|
+ } catch (e: any) {
|
|
|
+ ElMessage.error(e?.message || '提交检验结果失败');
|
|
|
+ } finally {
|
|
|
+ flowSubmitting.value = false;
|
|
|
+ }
|
|
|
+}
|
|
|
+async function onFlowApprove() {
|
|
|
+ if (!currentDetailId.value) return;
|
|
|
+ flowSubmitting.value = true;
|
|
|
+ try {
|
|
|
+ await fqcSupervisorApprove(currentDetailId.value);
|
|
|
+ ElMessage.success('已通过');
|
|
|
+ await loadDetailAndState(currentDetailId.value);
|
|
|
+ loadBillList();
|
|
|
+ } catch (e: any) {
|
|
|
+ ElMessage.error(e?.message || '审核通过失败');
|
|
|
+ } finally {
|
|
|
+ flowSubmitting.value = false;
|
|
|
+ }
|
|
|
+}
|
|
|
+async function onFlowReject(comment: string) {
|
|
|
+ if (!currentDetailId.value) return;
|
|
|
+ flowSubmitting.value = true;
|
|
|
+ try {
|
|
|
+ await fqcSupervisorReject(currentDetailId.value, comment);
|
|
|
+ ElMessage.success('已退回');
|
|
|
+ await loadDetailAndState(currentDetailId.value);
|
|
|
+ loadBillList();
|
|
|
+ loadEntryList();
|
|
|
+ } catch (e: any) {
|
|
|
+ ElMessage.error(e?.message || '退回失败');
|
|
|
+ } finally {
|
|
|
+ flowSubmitting.value = false;
|
|
|
+ }
|
|
|
+}
|
|
|
+async function onFlowQe(payload: FqcQeDispositionPayload) {
|
|
|
+ flowSubmitting.value = true;
|
|
|
+ try {
|
|
|
+ await submitFqcQeDisposition(payload);
|
|
|
+ ElMessage.success('QE 处置已提交');
|
|
|
+ if (currentDetailId.value) await loadDetailAndState(currentDetailId.value);
|
|
|
+ loadBillList();
|
|
|
+ } catch (e: any) {
|
|
|
+ ElMessage.error(e?.message || '提交 QE 处置失败');
|
|
|
+ } finally {
|
|
|
+ flowSubmitting.value = false;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function onTabChange(name: string | number) {
|
|
|
+ if (name === 'entry') loadEntryList();
|
|
|
+ else loadBillList();
|
|
|
+}
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ loadEntryList();
|
|
|
+ loadBillList();
|
|
|
+});
|
|
|
+onActivated(() => {
|
|
|
+ loadEntryList();
|
|
|
+});
|
|
|
</script>
|
|
|
|
|
|
<style scoped lang="scss">
|