<template>
|
<div class="app-container">
|
<div class="search_form">
|
<el-form :model="searchForm"
|
:inline="true">
|
<el-form-item label="生产订单号:">
|
<el-input v-model="searchForm.npsNo"
|
placeholder="请输入"
|
clearable
|
prefix-icon="Search"
|
style="width: 160px;"
|
@change="handleQuery" />
|
</el-form-item>
|
<el-form-item label="产品名称:">
|
<el-input v-model="searchForm.productName"
|
placeholder="请输入"
|
clearable
|
prefix-icon="Search"
|
style="width: 160px;"
|
@change="handleQuery" />
|
</el-form-item>
|
<el-form-item label="规格:">
|
<el-input v-model="searchForm.model"
|
placeholder="请输入"
|
clearable
|
prefix-icon="Search"
|
style="width: 160px;"
|
@change="handleQuery" />
|
</el-form-item>
|
<el-form-item label="状态:">
|
<el-select v-model="searchForm.status"
|
placeholder="请选择"
|
style="width: 160px;"
|
@change="handleQuery">
|
<el-option label="待开始"
|
value="1" />
|
<el-option label="进行中"
|
value="2" />
|
<el-option label="已完成"
|
value="3" />
|
<el-option label="已取消"
|
value="4" />
|
<el-option label="已结束"
|
value="5" />
|
</el-select>
|
</el-form-item>
|
<el-form-item>
|
<el-button type="primary"
|
@click="handleQuery">搜索</el-button>
|
<el-button type="info"
|
@click="handleReset">重置</el-button>
|
</el-form-item>
|
</el-form>
|
<div class="action-buttons">
|
<!-- <el-button type="primary"
|
@click="isShowNewModal = true">新增</el-button> -->
|
<el-button type="danger"
|
@click="handleDelete">退回</el-button>
|
<el-button @click="handleOut">导出</el-button>
|
</div>
|
</div>
|
<div class="table_list">
|
<PIMTable rowKey="id"
|
:column="tableColumn"
|
:tableData="tableData"
|
:page="page"
|
:tableLoading="tableLoading"
|
:row-class-name="tableRowClassName"
|
:isSelection="true"
|
:selectable="row => !row.endOrder"
|
@selection-change="handleSelectionChange"
|
@pagination="pagination">
|
<template #completionStatus="{ row }">
|
<el-progress :percentage="toProgressPercentage(row?.completionStatus)"
|
:color="progressColor(toProgressPercentage(row?.completionStatus))"
|
:status="toProgressPercentage(row?.completionStatus) >= 100 ? 'success' : ''" />
|
</template>
|
<template #processRouteStatus="{ row }">
|
<div v-if="row.processRouteStatus && row.processRouteStatus.length"
|
class="process-progress-container">
|
<div v-for="(item, index) in row.processRouteStatus"
|
:key="index"
|
class="process-step">
|
<div class="step-content">
|
<div class="step-circle"
|
:class="{ 'is-completed': item.percentage >= 100 }">
|
<span class="step-percentage"
|
:style="{ color: item.percentage >= 70 ? item.percentage >= 100 ? '#67c23a' : '#f56c6c' : '#000' }">{{ item.percentage }}%</span>
|
</div>
|
<div class="step-name">{{ item.name }}</div>
|
</div>
|
<div v-if="index < row.processRouteStatus.length - 1"
|
class="step-line"></div>
|
</div>
|
</div>
|
<span v-else>-</span>
|
</template>
|
</PIMTable>
|
</div>
|
<el-dialog v-model="bindRouteDialogVisible"
|
title="绑定工艺路线"
|
width="500px">
|
<el-form label-width="90px">
|
<el-form-item label="工艺路线">
|
<el-select v-model="bindForm.routeId"
|
placeholder="请选择工艺路线"
|
style="width: 100%;"
|
:loading="bindRouteLoading">
|
<el-option v-for="item in routeOptions"
|
:key="item.id"
|
:label="`${item.processRouteCode || ''}`"
|
:value="item.id" />
|
</el-select>
|
</el-form-item>
|
</el-form>
|
<template #footer>
|
<span class="dialog-footer">
|
<el-button type="primary"
|
:loading="bindRouteSaving"
|
@click="handleBindRouteConfirm">确 认</el-button>
|
<el-button @click="bindRouteDialogVisible = false">取 消</el-button>
|
</span>
|
</template>
|
</el-dialog>
|
<!-- 来源数据弹窗 -->
|
<el-dialog v-model="sourceDataDialogVisible"
|
title="来源数据"
|
width="1200px">
|
<div v-if="sourceRowData"
|
class="applyno-summary1">
|
<div class="summary-item">
|
<span class="summary-label">产品名称:</span>
|
<span class="summary-value">
|
<el-tag type="primary">{{ sourceRowData.productName || '-' }}</el-tag>
|
</span>
|
</div>
|
<div class="summary-item">
|
<span class="summary-label">规格:</span>
|
<span class="summary-value">{{ sourceRowData.model || '-' }}</span>
|
</div>
|
<div class="summary-item">
|
<span class="summary-label">订单需求数量:</span>
|
<span class="summary-value">{{ sourceRowData.quantity || 0 }}</span>
|
</div>
|
</div>
|
<div class="source-table-container">
|
<div class="source-data-cards-container">
|
<div v-for="(item, index) in sourceTableData"
|
:key="index"
|
class="source-data-card">
|
<div class="card-body">
|
<div class="info-grid">
|
<div class="info-item">
|
<div class="info-label">计划号</div>
|
<div class="info-value">{{ item.mpsNo || '-' }}</div>
|
</div>
|
<div class="info-item">
|
<div class="info-label">数据来源</div>
|
<div class="info-value">
|
<el-tag :type="item.source === '销售' ? 'primary' : 'warning'">
|
{{ item.source || '未知' }}
|
</el-tag>
|
</div>
|
</div>
|
<div class="info-item">
|
<div class="info-label">合同号</div>
|
<div class="info-value">{{ item.salesContractNo || '-' }}</div>
|
</div>
|
<div class="info-item">
|
<div class="info-label">客户名称</div>
|
<div class="info-value">{{ item.customerName || '-' }}</div>
|
</div>
|
<div class="info-item">
|
<div class="info-label">项目名称</div>
|
<div class="info-value">{{ item.projectName || '-' }}</div>
|
</div>
|
<div class="info-item">
|
<div class="info-label">计划需求数量</div>
|
<div class="info-value">{{ item.qtyRequired || 0 }} {{ item.unit || '' }}</div>
|
</div>
|
<div class="info-item">
|
<div class="info-label">单位</div>
|
<div class="info-value">{{ item.unit || '-' }}</div>
|
</div>
|
<div class="info-item">
|
<div class="info-label">需求日期</div>
|
<div class="info-value">{{ item.requiredDate ? dayjs(item.requiredDate).format('YYYY-MM-DD') : '-' }}</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
</el-dialog>
|
<MaterialLedgerDialog v-model="materialDialogVisible"
|
:order-row="currentMaterialOrder"
|
@saved="getList" />
|
<MaterialDetailDialog v-model="materialDetailDialogVisible"
|
:order-row="currentMaterialDetailOrder"
|
@confirmed="getList" />
|
<MaterialSupplementDialog v-model="materialSupplementDialogVisible"
|
:order-row="currentMaterialSupplementOrder"
|
@saved="getList" />
|
<new-product-order v-if="isShowNewModal"
|
v-model:visible="isShowNewModal"
|
@completed="handleQuery" />
|
<!-- 打印领料单组件 -->
|
<div class="print-requisition-wrapper">
|
<PrintMaterialRequisition ref="printRef"
|
:order-row="printOrderRow"
|
:material-list="printMaterialList" />
|
</div>
|
</div>
|
</template>
|
|
<script setup>
|
import {
|
computed,
|
defineAsyncComponent,
|
getCurrentInstance,
|
onMounted,
|
reactive,
|
ref,
|
toRefs,
|
} from "vue";
|
import { ElMessageBox } from "element-plus";
|
import dayjs from "dayjs";
|
import { useRouter } from "vue-router";
|
import {
|
productOrderListPage,
|
listProcessRoute,
|
bindingRoute,
|
listProcessBom,
|
delProductOrder,
|
getProductOrderSource,
|
updateProductOrder,
|
} from "@/api/productionManagement/productionOrder.js";
|
import { productWorkOrderPage } from "@/api/productionManagement/workOrder.js";
|
import { listMain as getOrderProcessRouteMain } from "@/api/productionManagement/productProcessRoute.js";
|
import MaterialLedgerDialog from "@/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue";
|
import MaterialDetailDialog from "@/views/productionManagement/productionOrder/components/MaterialDetailDialog.vue";
|
import MaterialSupplementDialog from "@/views/productionManagement/productionOrder/components/MaterialSupplementDialog.vue";
|
import PrintMaterialRequisition from "@/views/productionManagement/productionOrder/components/PrintMaterialRequisition.vue";
|
import PIMTable from "@/components/PIMTable/PIMTable.vue";
|
import { listPage } from "@/api/productionManagement/processRoute.js";
|
import {
|
listMaterialPickingDetail,
|
listMaterialPickingBom,
|
} from "@/api/productionManagement/productionOrder.js";
|
const NewProductOrder = defineAsyncComponent(() =>
|
import("@/views/productionManagement/productionOrder/New.vue")
|
);
|
|
const { proxy } = getCurrentInstance();
|
|
const router = useRouter();
|
const isShowNewModal = ref(false);
|
const sourceDataDialogVisible = ref(false);
|
const sourceTableData = ref([]);
|
const sourceRowData = ref(null);
|
const sourcePage = reactive({
|
total: 0,
|
});
|
|
const processColumnWidth = computed(() => {
|
if (!tableData.value || tableData.value.length === 0) return "200px";
|
const maxProcesses = Math.max(
|
...tableData.value.map(row => row.processRouteStatus?.length || 0)
|
);
|
if (maxProcesses === 0) return "100px";
|
// 每个工序圆圈 36px + 线条 30px = 66px,额外加 60px 边距和文字空间
|
return `${maxProcesses * 66 + 60}px`;
|
});
|
|
const tableColumn = computed(() => [
|
{
|
label: "生产订单号",
|
prop: "npsNo",
|
width: "150px",
|
},
|
// 1.待开始、2.进行中、3.已完成、4.已取消、5.已结束
|
{
|
label: "状态",
|
prop: "status",
|
width: "150px",
|
dataType: "tag",
|
formatData: val =>
|
val === 1
|
? "待开始"
|
: val === 2
|
? "进行中"
|
: val === 3
|
? "已完成"
|
: val === 5
|
? "已结束"
|
: "已取消",
|
formatType: val =>
|
val === 1
|
? "primary"
|
: val === 2
|
? "warning"
|
: val === 3
|
? "success"
|
: val === 5
|
? "danger"
|
: "info",
|
},
|
{
|
label: "产品名称",
|
prop: "productName",
|
width: "120px",
|
},
|
{
|
label: "规格",
|
prop: "model",
|
width: "120px",
|
},
|
{
|
label: "工艺路线编号",
|
prop: "processRouteCode",
|
width: "200px",
|
},
|
{
|
label: "需求数量",
|
prop: "quantity",
|
},
|
{
|
label: "完成数量",
|
prop: "completeQuantity",
|
},
|
{
|
label: "工序生产进度",
|
prop: "processRouteStatus",
|
dataType: "slot",
|
slot: "processRouteStatus",
|
width: processColumnWidth.value,
|
},
|
{
|
dataType: "slot",
|
label: "完成进度",
|
prop: "completionStatus",
|
slot: "completionStatus",
|
width: 180,
|
},
|
{
|
label: "开始日期",
|
prop: "startTime",
|
formatData: val => (val ? dayjs(val).format("YYYY-MM-DD") : ""),
|
width: 120,
|
},
|
{
|
label: "结束日期",
|
prop: "endTime",
|
formatData: val => (val ? dayjs(val).format("YYYY-MM-DD") : ""),
|
width: 120,
|
},
|
{
|
label: "计划完成时间",
|
prop: "planCompleteTime",
|
formatData: val => (val ? dayjs(val).format("YYYY-MM-DD") : ""),
|
width: 120,
|
},
|
{
|
dataType: "action",
|
label: "操作",
|
align: "center",
|
fixed: "right",
|
width: 280,
|
operation: [
|
{
|
name: "工艺路线",
|
type: "text",
|
showHide: row => row.processRouteCode,
|
clickFun: row => {
|
showRouteItemModal(row);
|
},
|
},
|
{
|
name: "绑定工艺路线",
|
type: "text",
|
showHide: row => !row.processRouteCode && !row.endOrder,
|
clickFun: row => {
|
openBindRouteDialog(row, "add");
|
},
|
},
|
{
|
name: "更换工艺路线",
|
type: "text",
|
showHide: row => row.processRouteCode && !row.endOrder,
|
clickFun: row => {
|
openBindRouteDialog(row, "change");
|
},
|
},
|
{
|
name: "来源",
|
type: "text",
|
clickFun: row => {
|
showSourceData(row);
|
},
|
},
|
{
|
name: "领料",
|
type: "text",
|
color: "#5EC7AB",
|
showHide: row => !row.endOrder && !row.returned,
|
clickFun: row => {
|
openMaterialDialog(row);
|
},
|
},
|
{
|
name: "补料",
|
type: "text",
|
color: "#5EC7AB",
|
showHide: row => !row.endOrder && !row.returned,
|
clickFun: row => {
|
openMaterialSupplementDialog(row);
|
},
|
},
|
{
|
name: "领料详情",
|
type: "text",
|
color: "#5EC7AB",
|
clickFun: row => {
|
openMaterialDetailDialog(row);
|
},
|
},
|
{
|
name: "打印领料单",
|
type: "text",
|
color: "#5EC7AB",
|
showHide: row => !row.endOrder,
|
clickFun: row => {
|
handlePrint(row);
|
},
|
},
|
{
|
name: "生产追溯",
|
type: "text",
|
color: "#409eff",
|
clickFun: row => {
|
router.push({
|
path: "/productionManagement/productionTraceability",
|
query: {
|
npsNo: row.npsNo,
|
productName: row.productName,
|
model: row.model,
|
},
|
});
|
},
|
},
|
{
|
name: "结束订单",
|
type: "text",
|
color: "red",
|
showHide: row => !row.endOrder,
|
clickFun: row => {
|
handleEndOrder(row);
|
},
|
},
|
],
|
},
|
]);
|
const tableData = ref([]);
|
const tableLoading = ref(false);
|
const page = reactive({
|
current: 1,
|
size: 100,
|
total: 0,
|
});
|
const selectedRows = ref([]);
|
|
const data = reactive({
|
searchForm: {
|
npsNo: "",
|
customerName: "",
|
salesContractNo: "",
|
projectName: "",
|
productName: "",
|
model: "",
|
status: "",
|
},
|
});
|
const { searchForm } = toRefs(data);
|
|
const toProgressPercentage = val => {
|
const n = Number(val);
|
if (!Number.isFinite(n)) return 0;
|
if (n <= 0) return 0;
|
if (n >= 100) return 100;
|
return Math.round(n);
|
};
|
|
// 30/50/80/100 分段颜色:红/橙/蓝/绿
|
const progressColor = percentage => {
|
const p = toProgressPercentage(percentage);
|
if (p < 30) return "#f56c6c";
|
if (p < 50) return "#e6a23c";
|
if (p < 80) return "#409eff";
|
return "#67c23a";
|
};
|
|
// 添加表行类名方法
|
const tableRowClassName = ({ row }) => {
|
if (!row.planCompleteTime) return "";
|
if (row.isFh) return "";
|
|
const diff = row.deliveryDaysDiff;
|
if (diff === 15) {
|
return "yellow";
|
} else if (diff === 10) {
|
return "pink";
|
} else if (diff === 2) {
|
return "purple";
|
} else if (diff < 2) {
|
return "red";
|
}
|
};
|
|
// 绑定工艺路线弹框
|
const bindRouteDialogVisible = ref(false);
|
const bindRouteLoading = ref(false);
|
const bindRouteSaving = ref(false);
|
const routeOptions = ref([]);
|
const bindForm = reactive({
|
orderId: null,
|
routeId: null,
|
});
|
const materialDialogVisible = ref(false);
|
const currentMaterialOrder = ref(null);
|
const materialDetailDialogVisible = ref(false);
|
const currentMaterialDetailOrder = ref(null);
|
const materialSupplementDialogVisible = ref(false);
|
const currentMaterialSupplementOrder = ref(null);
|
|
// 打印相关
|
const printOrderRow = ref(null);
|
const printMaterialList = ref([]);
|
const handlePrint = async row => {
|
printOrderRow.value = row;
|
proxy.$modal.loading("正在获取领料数据...");
|
try {
|
printMaterialList.value = [];
|
const detailRes = await listMaterialPickingDetail(row.id);
|
const detailList = Array.isArray(detailRes?.data)
|
? detailRes.data
|
: detailRes?.data?.records || [];
|
|
if (detailList.length > 0) {
|
printMaterialList.value = detailList;
|
}
|
|
if (printMaterialList.value.length === 0) {
|
proxy.$modal.msgWarning("暂无领料数据");
|
return;
|
}
|
|
// 等待 DOM 更新后执行打印
|
proxy.$nextTick(() => {
|
setTimeout(() => {
|
window.print();
|
}, 800);
|
});
|
} catch (e) {
|
console.error("获取领料数据失败:", e);
|
proxy.$modal.msgError("获取领料数据失败");
|
} finally {
|
proxy.$modal.closeLoading();
|
}
|
};
|
|
const openBindRouteDialog = async (row, type) => {
|
bindForm.orderId = row.id;
|
bindForm.routeId = type === "add" ? null : row.processRouteCode;
|
bindRouteDialogVisible.value = true;
|
routeOptions.value = [];
|
if (!row.productModelId) {
|
proxy.$modal.msgWarning("当前订单缺少产品型号,无法查询工艺路线");
|
bindRouteDialogVisible.value = false;
|
return;
|
}
|
bindRouteLoading.value = true;
|
try {
|
const res = await listPage({ productModelId: row.productModelId });
|
routeOptions.value = res.data.records || [];
|
} catch (e) {
|
console.error("获取工艺路线列表失败:", e);
|
proxy.$modal.msgError("获取工艺路线列表失败");
|
} finally {
|
bindRouteLoading.value = false;
|
}
|
};
|
|
const handleBindRouteConfirm = async () => {
|
if (!bindForm.routeId) {
|
proxy.$modal.msgWarning("请选择工艺路线");
|
return;
|
}
|
bindRouteSaving.value = true;
|
try {
|
await bindingRoute({
|
id: bindForm.orderId,
|
technologyRoutingId: bindForm.routeId,
|
});
|
proxy.$modal.msgSuccess("绑定成功");
|
bindRouteDialogVisible.value = false;
|
getList();
|
} catch (e) {
|
console.error("绑定工艺路线失败:", e);
|
proxy.$modal.msgError("绑定工艺路线失败");
|
} finally {
|
bindRouteSaving.value = false;
|
}
|
};
|
|
const openMaterialDialog = row => {
|
currentMaterialOrder.value = row;
|
materialDialogVisible.value = true;
|
};
|
|
const openMaterialDetailDialog = async row => {
|
currentMaterialDetailOrder.value = row;
|
materialDetailDialogVisible.value = true;
|
};
|
|
const openMaterialSupplementDialog = row => {
|
currentMaterialSupplementOrder.value = row;
|
materialSupplementDialogVisible.value = true;
|
};
|
|
const handleReset = () => {
|
searchForm.value = {
|
...searchForm.value,
|
npsNo: "",
|
customerName: "",
|
salesContractNo: "",
|
projectName: "",
|
productName: "",
|
model: "",
|
status: "",
|
};
|
handleQuery();
|
};
|
|
// 查询列表
|
/** 搜索按钮操作 */
|
const handleQuery = () => {
|
page.current = 1;
|
getList();
|
};
|
const pagination = obj => {
|
page.current = obj.page;
|
page.size = obj.limit;
|
getList();
|
};
|
const changeDaterange = value => {
|
if (value) {
|
searchForm.value.entryDateStart = value[0];
|
searchForm.value.entryDateEnd = value[1];
|
} else {
|
searchForm.value.entryDateStart = undefined;
|
searchForm.value.entryDateEnd = undefined;
|
}
|
handleQuery();
|
};
|
const getList = () => {
|
tableLoading.value = true;
|
// 构造一个新的对象,不包含entryDate字段
|
const params = { ...searchForm.value, ...page };
|
params.entryDate = undefined;
|
productOrderListPage(params)
|
.then(async res => {
|
const records = res.data.records || [];
|
// 为每个订单查询对应的工序进度数据
|
const processPromises = records.map(async item => {
|
if (item.npsNo) {
|
try {
|
const workOrderRes = await productWorkOrderPage({
|
npsNo: item.npsNo,
|
size: 100,
|
});
|
const workOrders = workOrderRes.data.records || [];
|
// 按照工序顺序排序(如果有顺序字段,假设为 orderNum 或按返回顺序)
|
// 转换为 processRouteStatus 格式
|
const processRouteStatus = workOrders.map(wo => ({
|
name: wo.operationName || "未知工序",
|
percentage: wo.completionStatus > 100 ? 100 : wo.completionStatus,
|
}));
|
return { ...item, processRouteStatus };
|
} catch (error) {
|
console.error(`获取工单 ${item.npsNo} 进度失败:`, error);
|
return { ...item, processRouteStatus: [] };
|
}
|
}
|
return { ...item, processRouteStatus: [] };
|
});
|
|
tableData.value = await Promise.all(processPromises);
|
page.total = res.data.total;
|
tableLoading.value = false;
|
})
|
.catch(() => {
|
tableLoading.value = false;
|
});
|
};
|
|
const showRouteItemModal = async row => {
|
const orderId = row.id;
|
try {
|
const res = await getOrderProcessRouteMain(orderId);
|
const data = res.data || {};
|
if (!data || !data.id) {
|
proxy.$modal.msgWarning("未找到关联的工艺路线");
|
return;
|
}
|
router.push({
|
path: "/productionManagement/processRouteItem",
|
query: {
|
id: data.id,
|
bomId: data.orderBomId,
|
processRouteCode: data.processRouteCode || "",
|
productName: row.productName || "",
|
model: row.model || "",
|
bomNo: row.bomNo || "",
|
description: data.description || "",
|
quantity: row.quantity || 0,
|
orderId,
|
type: "order",
|
editable: !row.endOrder,
|
},
|
});
|
} catch (e) {
|
console.error("获取工艺路线主信息失败:", e);
|
proxy.$modal.msgError("获取工艺路线信息失败");
|
}
|
};
|
|
const showProductStructure = row => {
|
router.push({
|
path: "/productionManagement/productStructureDetail",
|
query: {
|
id: row.id,
|
bomNo: row.bomNo || "",
|
productName: row.productName || "",
|
productModelName: row.model || "",
|
orderId: row.id,
|
type: "order",
|
},
|
});
|
};
|
|
// 查看来源生产计划数据
|
const showSourceData = row => {
|
// 存储点击来源按钮时传递的row参数
|
sourceRowData.value = row;
|
// 调用API获取来源数据
|
getProductOrderSource(row.id)
|
.then(res => {
|
if (res.code === 200) {
|
// 直接存储返回的扁平化数据
|
sourceTableData.value = res.data || [];
|
sourcePage.total = sourceTableData.value.length;
|
// 打开弹窗
|
sourceDataDialogVisible.value = true;
|
} else {
|
proxy.$modal.msgError(res.msg || "获取来源数据失败");
|
}
|
})
|
.catch(err => {
|
proxy.$modal.msgError("获取来源数据失败");
|
console.error(err);
|
});
|
};
|
|
// 表格选择数据
|
const handleSelectionChange = selection => {
|
selectedRows.value = selection;
|
};
|
|
const handleDelete = () => {
|
let ids = [];
|
if (selectedRows.value.length > 0) {
|
ids = selectedRows.value.map(item => item.id);
|
} else {
|
proxy.$modal.msgWarning("请选择数据");
|
return;
|
}
|
ElMessageBox.confirm("是否退回该生产订单?", "退回", {
|
confirmButtonText: "确认",
|
cancelButtonText: "取消",
|
type: "warning",
|
})
|
.then(() => {
|
console.log(ids, "ids");
|
delProductOrder(ids).then(res => {
|
proxy.$modal.msgSuccess("退回成功");
|
getList();
|
});
|
})
|
.catch(() => {
|
proxy.$modal.msg("已取消");
|
});
|
};
|
|
// 导出
|
const handleOut = () => {
|
ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
|
confirmButtonText: "确认",
|
cancelButtonText: "取消",
|
type: "warning",
|
})
|
.then(() => {
|
proxy.download(
|
"/productOrder/export",
|
{ ...searchForm.value },
|
"生产订单.xlsx"
|
);
|
})
|
.catch(() => {
|
proxy.$modal.msg("已取消");
|
});
|
};
|
|
// 结束订单
|
const handleEndOrder = row => {
|
ElMessageBox.confirm(`是否确认结束订单:${row.npsNo}?`, "提示", {
|
confirmButtonText: "确定",
|
cancelButtonText: "取消",
|
type: "warning",
|
})
|
.then(() => {
|
const params = {
|
id: row.id,
|
endOrder: true,
|
};
|
updateProductOrder(params).then(() => {
|
proxy.$modal.msgSuccess("结束订单成功");
|
getList();
|
});
|
})
|
.catch(() => {});
|
};
|
|
const handleConfirmRoute = () => {};
|
|
onMounted(() => {
|
getList();
|
});
|
</script>
|
|
<style scoped lang="scss">
|
.search_form {
|
align-items: start;
|
}
|
|
.action-buttons {
|
display: flex;
|
flex-wrap: nowrap;
|
gap: 8px;
|
}
|
|
:deep(.yellow) {
|
background-color: #faf0de;
|
}
|
|
:deep(.pink) {
|
background-color: #fae1de;
|
}
|
|
:deep(.red) {
|
background-color: #f80202;
|
}
|
|
:deep(.purple) {
|
background-color: #f4defa;
|
}
|
.table_list {
|
margin-top: unset;
|
}
|
|
.process-progress-container {
|
display: inline-flex;
|
align-items: center;
|
padding: 10px 0;
|
white-space: nowrap;
|
|
.process-step {
|
display: flex;
|
align-items: center;
|
position: relative;
|
|
.step-content {
|
display: flex;
|
flex-direction: column;
|
align-items: center;
|
z-index: 1;
|
|
.step-circle {
|
width: 36px;
|
height: 36px;
|
border-radius: 50%;
|
border: 2px solid #409eff;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
background-color: #fff;
|
margin-bottom: 4px;
|
|
.step-percentage {
|
font-size: 11px;
|
font-weight: bold;
|
}
|
|
&.is-completed {
|
border-color: #67c23a;
|
.step-percentage {
|
color: #67c23a;
|
}
|
}
|
}
|
|
.step-name {
|
font-size: 12px;
|
color: #606266;
|
white-space: nowrap;
|
}
|
}
|
|
.step-line {
|
width: 30px;
|
height: 1px;
|
background-color: #dcdfe6;
|
margin: 0 -2px;
|
margin-top: -20px; // 向上偏移以对齐圆心
|
}
|
}
|
}
|
</style>
|
<style lang="scss">
|
.status-cell {
|
font-weight: 600;
|
color: #409eff;
|
font-family: "Courier New", monospace;
|
text-shadow: 0 1px 2px rgba(64, 158, 255, 0.2);
|
}
|
|
.source-table-container {
|
margin-top: 20px;
|
}
|
|
.source-data-cards-container {
|
display: flex;
|
flex-direction: column;
|
gap: 16px;
|
max-height: 500px;
|
overflow-y: auto;
|
padding: 10px;
|
background-color: #f5f7fa;
|
border-radius: 4px;
|
padding-bottom: 20px;
|
|
.source-data-card {
|
background: #fff;
|
border-radius: 8px;
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
overflow: hidden;
|
|
.card-body {
|
padding: 20px;
|
|
.info-grid {
|
display: grid;
|
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
gap: 16px;
|
|
.info-item {
|
display: flex;
|
flex-direction: column;
|
|
.info-label {
|
font-size: 12px;
|
color: #909399;
|
margin-bottom: 4px;
|
font-weight: 500;
|
}
|
|
.info-value {
|
font-size: 14px;
|
color: #303133;
|
font-weight: 500;
|
}
|
}
|
}
|
}
|
}
|
}
|
|
.applyno-summary1 {
|
padding: 16px 20px;
|
background: #f5f7fa;
|
border-bottom: 1px solid #e4e7ed;
|
display: flex;
|
flex-wrap: wrap;
|
gap: 16px;
|
|
.summary-item {
|
display: flex;
|
align-items: center;
|
margin-right: 20px;
|
|
.summary-label {
|
font-size: 13px;
|
color: #909399;
|
margin-right: 8px;
|
font-weight: 500;
|
}
|
|
.summary-value {
|
font-size: 14px;
|
color: #303133;
|
font-weight: 500;
|
}
|
}
|
}
|
</style>
|