<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-select v-model="searchForm.strength"
|
style="width: 200px;"
|
placeholder="请选择产品类型"
|
clearable
|
@change="handleQuery">
|
<el-option v-for="option in productTypeOptions2"
|
:key="option.dictLabel"
|
:label="option.dictLabel"
|
:value="option.dictLabel" />
|
</el-select>
|
</el-form-item>
|
<el-form-item label="创建时间:">
|
<el-date-picker v-model="createTime"
|
type="daterange"
|
range-separator="至"
|
start-placeholder="开始日期"
|
value-format="YYYY-MM-DD"
|
format="YYYY-MM-DD"
|
end-placeholder="结束日期"
|
style="width: 300px;"
|
@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 v-for="item in statusOptions"
|
:key="item.value"
|
:label="item.label"
|
:value="item.value" />
|
</el-select>
|
</el-form-item>
|
<el-form-item>
|
<el-button type="primary"
|
@click="handleQuery">搜索</el-button>
|
<el-button type="primary"
|
@click="handleReset">重置</el-button>
|
<el-button type="danger"
|
@click="handleDelete">退回</el-button>
|
<el-button @click="handleOut">导出</el-button>
|
</el-form-item>
|
</el-form>
|
<!-- <div style="width:350px;text-align:right;">
|
</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.status != 4"
|
@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 #quantity="{ row }">
|
{{ row.quantity || '-' }}<span style="color:rgb(63, 95, 211)"> 块</span>
|
</template>
|
<template #completeQuantity="{ row }">
|
{{ row.completeQuantity || '-' }}<span style="color:rgb(42, 169, 146)"> 方</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 @click="bindRouteDialogVisible = false">取 消</el-button>
|
<el-button type="primary"
|
:loading="bindRouteSaving"
|
@click="handleBindRouteConfirm">确 认</el-button>
|
</span>
|
</template>
|
</el-dialog>
|
<new-product-order v-if="isShowNewModal"
|
v-model:visible="isShowNewModal"
|
@completed="handleQuery" />
|
<!-- 来源数据弹窗 -->
|
<el-dialog v-model="sourceDataDialogVisible"
|
title="来源数据"
|
width="1000px">
|
<div 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.materialCode || '-' }}</span>
|
</div>
|
<div class="summary-item">
|
<span class="summary-label">强度:</span>
|
<span class="summary-value">{{ sourceRowData.strength || '-' }}</span>
|
</div>
|
</div>
|
<div class="source-data-container">
|
<!-- 左侧applyNo列表 -->
|
<div class="applyno-list">
|
<div class="list-header">申请单列表</div>
|
<div class="list-body">
|
<div v-for="(item, index) in sourceTableData"
|
:key="item.applyNo || index"
|
class="applyno-item"
|
:class="{ active: selectedApplyNo === item.applyNo }"
|
@click="selectApplyNo(item)">
|
<div class="applyno-text">{{ item.applyNo }}</div>
|
<div class="applyno-info">{{ item.customerName }}</div>
|
</div>
|
</div>
|
</div>
|
<!-- 右侧详细信息 -->
|
<div class="detail-info">
|
<div v-if="selectedSourceData && selectedSourceData.items && selectedSourceData.items.length > 0">
|
<div v-for="item in selectedSourceData.items"
|
:key="item.id"
|
class="source-data-card">
|
<!-- <div class="card-header">
|
<div class="data-source-tag">
|
</div>
|
<div class="card-title">产品明细</div>
|
</div> -->
|
<div class="card-body">
|
<div class="info-grid">
|
<div class="info-item">
|
<div class="info-label">数据来源</div>
|
<div class="info-value">
|
<el-tag :type="item.dataSourceType == 1 ? 'primary' : 'warning'">
|
{{ item.dataSourceType == 1 ? '钉钉同步' : '手动新增' }}
|
</el-tag>
|
</div>
|
</div>
|
<div class="info-item">
|
<div class="info-label">块数</div>
|
<div class="info-value">{{ item.quantity || '-' }}<span style="color:rgb(63, 95, 211)"> 块</span></div>
|
</div>
|
<div class="info-item">
|
<div class="info-label">方数</div>
|
<div class="info-value">{{ item.volume || '-' }}<span style="color:rgba(27, 104, 90, 0.76)"> 方</span></div>
|
</div>
|
<div class="info-item">
|
<div class="info-label">下发状态</div>
|
<div class="info-value">
|
<el-tag :type="{
|
0: 'warning',
|
1: 'primary',
|
2: 'info'
|
}[item.status] || 'info'">
|
{{ item.status == 0 ? '待下发' : item.status == 1 ? '部分下发' : '已下发' }}
|
</el-tag>
|
</div>
|
</div>
|
<div class="info-item">
|
<div class="info-label">已下发方数</div>
|
<div class="info-value">{{ item.assignedQuantity ? `${item.assignedQuantity}` : 0 }}<span style="color:rgba(214, 134, 22, 0.76)"> 方</span></div>
|
</div>
|
<div class="info-item">
|
<div class="info-label">尺寸</div>
|
<div class="info-value">{{ item.length || '-' }}mm × {{ item.width || '-' }}mm × {{ item.height || '-' }}mm</div>
|
</div>
|
<div class="info-item">
|
<div class="info-label">计划开始日期</div>
|
<div class="info-value">{{ item.startDate ? dayjs(item.startDate).format('YYYY-MM-DD') : '' }}</div>
|
</div>
|
<div class="info-item">
|
<div class="info-label">计划结束日期</div>
|
<div class="info-value">{{ item.endDate ? dayjs(item.endDate).format('YYYY-MM-DD') : '' }}</div>
|
</div>
|
<!-- <div class="info-item">
|
<div class="info-label">强度</div>
|
<div class="info-value">{{ item.strength || '' }}</div>
|
</div> -->
|
</div>
|
<div class="remarks-section">
|
<div class="info-item full-width">
|
<div class="info-label">备注 1</div>
|
<div class="info-value">{{ item.remarkOne || '-' }}</div>
|
</div>
|
<div class="info-item full-width">
|
<div class="info-label">备注 2</div>
|
<div class="info-value">{{ item.remarkTwo || '-' }}</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
<div v-else
|
class="empty-state">
|
<el-empty :description="selectedSourceData ? '该申请单暂无数据' : '请选择一个申请单'" />
|
</div>
|
</div>
|
</div>
|
</el-dialog>
|
</div>
|
</template>
|
|
<script setup>
|
import { onMounted, ref } from "vue";
|
import { ElMessageBox } from "element-plus";
|
import dayjs from "dayjs";
|
import { useRouter } from "vue-router";
|
import { getDicts } from "@/api/system/dict/data";
|
import {
|
productOrderListPage,
|
listProcessRoute,
|
bindingRoute,
|
listProcessBom,
|
delProductOrder,
|
revokeProductOrder,
|
getProductOrderSource,
|
} from "@/api/productionManagement/productionOrder.js";
|
import { listPage } from "@/api/productionManagement/processRoute.js";
|
import { listMain as getOrderProcessRouteMain } from "@/api/productionManagement/productProcessRoute.js";
|
import { fileDel } from "@/api/financialManagement/revenueManagement.js";
|
import PIMTable from "@/components/PIMTable/PIMTable.vue";
|
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 selectedApplyNo = ref("");
|
const selectedSourceData = ref(null);
|
const sourceRowData = ref(null);
|
|
const tableColumn = ref([
|
{
|
label: "状态",
|
prop: "status",
|
dataType: "tag",
|
|
formatData: val => {
|
const statusMap = {
|
1: "待开始",
|
2: "进行中",
|
3: "已完成",
|
4: "已取消",
|
};
|
return statusMap[val] || "";
|
},
|
formatType: val => {
|
const statusMap = {
|
1: "error",
|
2: "warning",
|
3: "success",
|
4: "info",
|
};
|
return statusMap[val] || "info";
|
},
|
width: 100,
|
},
|
{
|
label: "生产订单号",
|
prop: "npsNo",
|
width: "120px",
|
},
|
{
|
label: "产品名称",
|
prop: "productName",
|
width: "120px",
|
dataType: "tag",
|
},
|
{
|
label: "规格",
|
prop: "model",
|
width: "120px",
|
},
|
{
|
label: "强度",
|
prop: "strength",
|
width: "120px",
|
dataType: "tag",
|
},
|
{
|
label: "物料编码",
|
prop: "materialCode",
|
width: "120px",
|
},
|
{
|
label: "工艺路线编号",
|
prop: "processRouteCode",
|
width: "200px",
|
className: "status-cell",
|
},
|
{
|
label: "需求数量",
|
prop: "quantity",
|
dataType: "slot",
|
align: "right",
|
slot: "quantity",
|
width: 120,
|
},
|
{
|
label: "完成数量",
|
prop: "completeQuantity",
|
dataType: "slot",
|
align: "right",
|
slot: "completeQuantity",
|
width: 120,
|
},
|
{
|
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,
|
},
|
{
|
label: "创建时间",
|
prop: "createTime",
|
formatData: val => (val ? dayjs(val).format("YYYY-MM-DD HH:mm:ss") : ""),
|
width: 120,
|
},
|
|
{
|
dataType: "action",
|
label: "操作",
|
align: "center",
|
fixed: "right",
|
width: 300,
|
operation: [
|
{
|
name: "来源",
|
type: "text",
|
clickFun: row => {
|
showSourceData(row);
|
},
|
},
|
{
|
name: "工艺路线",
|
type: "text",
|
clickFun: row => {
|
showRouteItemModal(row);
|
},
|
},
|
{
|
name: "绑定工艺路线",
|
type: "text",
|
showHide: row => !row.routeId,
|
clickFun: row => {
|
openBindRouteDialog(row);
|
},
|
},
|
{
|
name: "删除",
|
type: "text",
|
showHide: row => row.status == 4,
|
clickFun: row => {
|
handleDeleteSolo(row);
|
},
|
},
|
// {
|
// name: "产品结构",
|
// type: "text",
|
// clickFun: row => {
|
// showProductStructure(row);
|
// },
|
// },
|
],
|
},
|
]);
|
const tableData = ref([]);
|
const tableLoading = ref(false);
|
const page = reactive({
|
current: 1,
|
size: 100,
|
total: 0,
|
});
|
const selectedRows = ref([]);
|
|
// 来源数据弹窗相关
|
const sourceTableColumn = ref([
|
{
|
label: "数据来源",
|
width: "100px",
|
prop: "dataSourceType",
|
dataType: "tag",
|
formatType: params => {
|
const typeMap = {
|
2: "warning",
|
1: "primary",
|
};
|
return typeMap[params] || "info";
|
},
|
formatData: cell => (cell == 1 ? "钉钉同步" : "手动新增"),
|
},
|
{
|
label: "申请单编号",
|
prop: "applyNo",
|
width: "150px",
|
},
|
{
|
label: "客户名称",
|
prop: "customerName",
|
width: "150px",
|
},
|
{
|
label: "产品名称",
|
prop: "productName",
|
width: "200px",
|
dataType: "tag",
|
formatType: params => {
|
return "primary";
|
},
|
},
|
{
|
label: "产品规格",
|
prop: "model",
|
width: "150px",
|
className: "spec-cell",
|
},
|
{
|
label: "物料编码",
|
prop: "materialCode",
|
width: "150px",
|
},
|
{
|
label: "块数",
|
prop: "quantity",
|
align: "right",
|
dataType: "slot",
|
slot: "quantity",
|
},
|
{
|
label: "方数",
|
prop: "volume",
|
width: "150px",
|
align: "right",
|
dataType: "slot",
|
slot: "volume",
|
className: "volume-cell",
|
},
|
{
|
label: "下发状态",
|
prop: "status",
|
width: "150px",
|
className: "status-cell",
|
dataType: "tag",
|
formatType: params => {
|
const typeMap = {
|
0: "warning",
|
1: "primary",
|
2: "info",
|
};
|
return typeMap[params] || "info";
|
},
|
formatData: cell => {
|
const statusMap = {
|
0: "待下发",
|
1: "部分下发",
|
2: "已下发",
|
};
|
return statusMap[cell] || "";
|
},
|
},
|
{
|
label: "已下发方数",
|
prop: "assignedQuantity",
|
width: "150px",
|
className: "spec-cell",
|
formatData: cell => (cell ? `${cell}方` : 0),
|
},
|
{
|
label: "长",
|
prop: "length",
|
className: "dimension-cell",
|
formatData: cell => (cell ? `${cell}mm` : ""),
|
},
|
{
|
label: "宽",
|
prop: "width",
|
className: "dimension-cell",
|
formatData: cell => (cell ? `${cell}mm` : ""),
|
},
|
{
|
label: "高",
|
prop: "height",
|
className: "dimension-cell",
|
formatData: cell => (cell ? `${cell}mm` : ""),
|
},
|
{
|
label: "计划开始日期",
|
prop: "startDate",
|
width: "150px",
|
className: "date-cell",
|
formatData: cell => (cell ? dayjs(cell).format("YYYY-MM-DD") : ""),
|
},
|
{
|
label: "计划结束日期",
|
prop: "endDate",
|
width: "150px",
|
className: "date-cell",
|
formatData: cell => (cell ? dayjs(cell).format("YYYY-MM-DD") : ""),
|
},
|
{
|
label: "强度",
|
prop: "strength",
|
formatData: cell => {
|
if (!cell) return "";
|
return cell;
|
},
|
},
|
{
|
label: "备注 1",
|
width: "150px",
|
prop: "remarkOne",
|
},
|
{
|
label: "备注 2",
|
width: "150px",
|
prop: "remarkTwo",
|
},
|
]);
|
const sourceTableLoading = ref(false);
|
const sourcePage = reactive({
|
current: 1,
|
size: 100,
|
total: 0,
|
});
|
|
const data = reactive({
|
searchForm: {
|
customerName: "",
|
salesContractNo: "",
|
projectName: "",
|
productName: "",
|
model: "",
|
dictCode: null,
|
startTime: null,
|
endTime: null,
|
strength: null,
|
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 productTypeOptions = ref([]);
|
const bindForm = reactive({
|
orderId: null,
|
routeId: null,
|
});
|
|
const openBindRouteDialog = async row => {
|
bindForm.orderId = row.id;
|
bindForm.routeId = null;
|
bindRouteDialogVisible.value = true;
|
routeOptions.value = [];
|
if (!row.model) {
|
proxy.$modal.msgWarning("当前订单缺少产品型号,无法查询工艺路线");
|
bindRouteDialogVisible.value = false;
|
return;
|
}
|
bindRouteLoading.value = true;
|
const distName =
|
row.productName == "板材"
|
? row.productName
|
: row.productName + "-" + row.strength;
|
|
try {
|
// 获取产品类型字典
|
const dictRes = await getDicts("product_type");
|
if (dictRes.code === 200) {
|
productTypeOptions.value = dictRes.data;
|
// 用distName匹配dictLabel,获取dictCode
|
const matchedType = productTypeOptions.value.find(
|
item => item.dictLabel === distName
|
);
|
const dictCode = matchedType ? matchedType.dictCode : row.productType;
|
|
// 使用dictCode查询工艺路线列表
|
const res = await listPage({ dictCode, status: true });
|
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,
|
routeId: bindForm.routeId,
|
});
|
proxy.$modal.msgSuccess("绑定成功");
|
bindRouteDialogVisible.value = false;
|
getList();
|
} catch (e) {
|
console.error("绑定工艺路线失败:", e);
|
proxy.$modal.msgError("绑定工艺路线失败");
|
} finally {
|
bindRouteSaving.value = false;
|
}
|
};
|
const statusOptions = ref([
|
{ value: 1, label: "待开始" },
|
{ value: 2, label: "进行中" },
|
{ value: 3, label: "已完成" },
|
{ value: 4, label: "已取消" },
|
]);
|
const handleReset = () => {
|
searchForm.value = {
|
customerName: "",
|
salesContractNo: "",
|
projectName: "",
|
productName: "",
|
model: "",
|
status: "",
|
strength: null,
|
startTime: null,
|
endTime: null,
|
};
|
createTime.value = [];
|
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 createTime = ref([]);
|
const getList = () => {
|
tableLoading.value = true;
|
// 构造一个新的对象,不包含entryDate字段
|
const params = { ...searchForm.value, ...page };
|
params.entryDate = undefined;
|
params.startTime =
|
createTime.value.length > 0
|
? dayjs(createTime.value[0]).format("YYYY-MM-DD HH:mm:ss")
|
: undefined;
|
params.endTime =
|
createTime.value.length > 0
|
? dayjs(createTime.value[1])
|
.hour(23)
|
.minute(59)
|
.second(59)
|
.format("YYYY-MM-DD HH:mm:ss")
|
: undefined;
|
|
productOrderListPage(params)
|
.then(res => {
|
tableLoading.value = false;
|
tableData.value = res.data.records;
|
page.total = res.data.total;
|
})
|
.catch(() => {
|
tableLoading.value = false;
|
});
|
};
|
|
const showRouteItemModal = async row => {
|
const orderId = row.id;
|
try {
|
router.push({
|
path: "/productionManagement/processRouteItem",
|
query: {
|
id: row.routeId,
|
processRouteCode: row.processRouteCode || "",
|
productName: row.productName || "",
|
model: row.model || "",
|
bomNo: row.bomNo || "",
|
bomId: row.bomId || "",
|
description: row.description || "",
|
dictLabel:
|
row.productName == "板材"
|
? row.productName
|
: row.productName + "-" + row.strength,
|
orderId: row.id,
|
type: "order",
|
editable: true,
|
},
|
});
|
} catch (e) {
|
console.error("获取工艺路线主信息失败:", e);
|
proxy.$modal.msgError("获取工艺路线信息失败");
|
}
|
};
|
|
const showProductStructure = row => {
|
if (!row.processRouteCode) {
|
proxy.$modal.msgWarning("请先绑定工艺路线");
|
return;
|
}
|
router.push({
|
path: "/productionManagement/productStructureDetail",
|
query: {
|
id: row.id,
|
bomNo: row.bomNo || "",
|
productName: row.productName || "",
|
productModelName: row.model || "",
|
orderId: row.id,
|
type: "order",
|
},
|
});
|
};
|
|
// 选择申请单
|
const selectApplyNo = item => {
|
selectedApplyNo.value = item.applyNo;
|
selectedSourceData.value = item;
|
};
|
|
// 查看来源生产计划数据
|
const showSourceData = row => {
|
// 存储点击来源按钮时传递的row参数
|
sourceRowData.value = row;
|
// 调用API获取来源数据
|
getProductOrderSource(row.id)
|
.then(res => {
|
if (res.code === 200) {
|
// 处理接口返回的数据,调整为我们需要的格式
|
sourceTableData.value = res.data.map(item => {
|
return {
|
applyNo: item.applyNo,
|
customerName: item.productPlans[0]?.customerName || "",
|
items: item.productPlans.map(plan => {
|
return {
|
id: plan.id,
|
dataSourceType: plan.dataSourceType,
|
productName: plan.productName,
|
model: plan.model,
|
materialCode: plan.materialCode,
|
quantity: plan.quantity,
|
volume: plan.volume,
|
status: plan.status,
|
assignedQuantity: plan.assignedQuantity,
|
length: plan.length,
|
width: plan.width,
|
height: plan.height,
|
startDate: plan.startDate,
|
endDate: plan.endDate,
|
strength: plan.strength,
|
remarkOne: plan.remarkOne,
|
remarkTwo: plan.remarkTwo,
|
};
|
}),
|
};
|
});
|
sourcePage.total = sourceTableData.value.length;
|
// 默认选择第一个申请单
|
if (sourceTableData.value.length > 0) {
|
selectApplyNo(sourceTableData.value[0]);
|
} else {
|
selectedApplyNo.value = "";
|
selectedSourceData.value = null;
|
}
|
// 打开弹窗
|
sourceDataDialogVisible.value = true;
|
} else {
|
proxy.$modal.msgError(res.msg || "获取来源数据失败");
|
}
|
})
|
.catch(err => {
|
proxy.$modal.msgError("获取来源数据失败");
|
console.error(err);
|
});
|
};
|
|
// 表格选择数据
|
const handleSelectionChange = selection => {
|
selectedRows.value = selection;
|
};
|
const handleDeleteSolo = row => {
|
ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "导出", {
|
confirmButtonText: "确认",
|
cancelButtonText: "取消",
|
type: "warning",
|
})
|
.then(() => {
|
delProductOrder(row.id).then(res => {
|
proxy.$modal.msgSuccess("删除成功");
|
getList();
|
});
|
})
|
.catch(() => {
|
proxy.$modal.msg("已取消");
|
});
|
};
|
|
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(() => {
|
revokeProductOrder(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 handleConfirmRoute = () => {};
|
const productTypeOptions2 = ref([]);
|
// 获取产品类型字典
|
const getProductTypeOptions = () => {
|
getDicts("block_strength")
|
.then(res => {
|
if (res.code === 200) {
|
productTypeOptions2.value = res.data;
|
}
|
})
|
.catch(err => {
|
console.error("获取产品类型字典失败:", err);
|
});
|
};
|
|
onMounted(() => {
|
getProductTypeOptions();
|
getList();
|
});
|
</script>
|
|
<style scoped lang="scss">
|
.search_form {
|
align-items: start;
|
}
|
|
::v-deep .yellow {
|
background-color: #faf0de;
|
}
|
|
::v-deep .pink {
|
background-color: #fae1de;
|
}
|
|
::v-deep .red {
|
background-color: #f80202;
|
}
|
|
::v-deep .purple {
|
background-color: #f4defa;
|
}
|
</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-data-container {
|
display: flex;
|
gap: 20px;
|
height: 500px;
|
|
.applyno-list {
|
width: 250px;
|
background: #fff;
|
border-radius: 8px;
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
overflow: hidden;
|
|
.list-header {
|
padding: 12px 16px;
|
background: #f5f7fa;
|
border-bottom: 1px solid #e4e7ed;
|
font-weight: 600;
|
color: #303133;
|
}
|
|
.list-body {
|
height: calc(100% - 48px);
|
overflow-y: auto;
|
|
.applyno-item {
|
padding: 12px 16px;
|
border-bottom: 1px solid #f0f2f5;
|
cursor: pointer;
|
transition: all 0.3s;
|
|
&:hover {
|
background: #f5f7fa;
|
}
|
|
&.active {
|
background: #ecf5ff;
|
border-left: 4px solid #409eff;
|
}
|
|
.applyno-text {
|
font-weight: 600;
|
color: #303133;
|
font-family: "Courier New", monospace;
|
margin-bottom: 4px;
|
}
|
|
.applyno-info {
|
font-size: 12px;
|
color: #909399;
|
}
|
}
|
}
|
}
|
|
.detail-info {
|
flex: 1;
|
background: #fff;
|
border-radius: 8px;
|
// box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
overflow: auto;
|
display: flex;
|
flex-direction: column;
|
|
.applyno-summary {
|
padding: 16px 20px;
|
background: #f5f7fa;
|
border-bottom: 1px solid #e4e7ed;
|
display: flex;
|
flex-wrap: wrap;
|
gap: 16px;
|
|
.summary-item {
|
display: flex;
|
align-items: center;
|
|
.summary-label {
|
font-size: 13px;
|
color: #909399;
|
margin-right: 8px;
|
font-weight: 500;
|
}
|
|
.summary-value {
|
font-size: 14px;
|
color: #303133;
|
font-weight: 500;
|
}
|
}
|
}
|
|
.empty-state {
|
flex: 1;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
}
|
|
.source-data-card {
|
flex: 1;
|
display: flex;
|
flex-direction: column;
|
overflow: hidden;
|
margin-top: 20px;
|
margin-right: 20px;
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
|
.card-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
padding: 16px 20px;
|
background: #f5f7fa;
|
border-bottom: 1px solid #e4e7ed;
|
|
.data-source-tag {
|
flex-shrink: 0;
|
}
|
|
.card-title {
|
font-weight: 600;
|
color: #303133;
|
font-size: 14px;
|
}
|
}
|
|
.card-body {
|
flex: 1;
|
padding: 20px;
|
overflow-y: auto;
|
background-color: #f5f7fa;
|
|
.info-grid {
|
display: grid;
|
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
gap: 16px;
|
margin-bottom: 20px;
|
|
.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;
|
}
|
}
|
|
.info-item.full-width {
|
grid-column: 1 / -1;
|
}
|
}
|
|
.remarks-section {
|
display: flex;
|
// flex-direction: column;
|
gap: 12px;
|
border-top: 1px solid #e4e7ed;
|
padding-top: 16px;
|
|
.info-item {
|
display: flex;
|
width: 50%;
|
flex-direction: column;
|
|
.info-label {
|
font-size: 12px;
|
color: #909399;
|
margin-bottom: 4px;
|
font-weight: 500;
|
}
|
|
.info-value {
|
font-size: 14px;
|
color: #303133;
|
line-height: 1.5;
|
padding: 8px;
|
background: #f9fafc;
|
border-radius: 4px;
|
border: 1px solid #ecf5ff;
|
}
|
}
|
}
|
}
|
}
|
}
|
}
|
.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>
|