<template>
|
<div class="app-container">
|
<div class="search_form">
|
<el-form :model="searchForm"
|
:inline="true">
|
<el-form-item label="委外订单号:">
|
<el-input v-model="searchForm.orderNo"
|
placeholder="请输入"
|
clearable
|
prefix-icon="Search"
|
style="width: 180px"
|
@change="handleQuery" />
|
</el-form-item>
|
<el-form-item label="合作商:">
|
<el-select v-model="searchForm.partnerId"
|
placeholder="请选择"
|
clearable
|
filterable
|
style="width: 200px"
|
@change="handleQuery">
|
<el-option v-for="item in partnerOptions"
|
:key="item.id"
|
:label="item.partnerName"
|
:value="item.id" />
|
</el-select>
|
</el-form-item>
|
<el-form-item label="项目名称:">
|
<el-input v-model="searchForm.projectName"
|
placeholder="请输入"
|
clearable
|
style="width: 160px"
|
@change="handleQuery" />
|
</el-form-item>
|
<el-form-item label="状态:">
|
<el-select v-model="searchForm.status"
|
placeholder="请选择"
|
clearable
|
style="width: 140px"
|
@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 label="申请日期:">
|
<el-date-picker v-model="dateRange"
|
type="daterange"
|
value-format="YYYY-MM-DD"
|
format="YYYY-MM-DD"
|
range-separator="至"
|
start-placeholder="开始日期"
|
end-placeholder="结束日期"
|
@change="handleQuery" />
|
</el-form-item>
|
<el-form-item>
|
<el-button type="primary"
|
@click="handleQuery">搜索</el-button>
|
<el-button @click="resetSearch">重置</el-button>
|
</el-form-item>
|
</el-form>
|
</div>
|
<div class="table_list">
|
<div class="actions">
|
<div></div>
|
<div>
|
<el-button type="primary"
|
@click="openForm('add')">新增委外订单</el-button>
|
<el-button @click="handleExport">导出</el-button>
|
<el-button type="danger"
|
plain
|
@click="handleBatchDelete">删除</el-button>
|
</div>
|
</div>
|
<el-table :data="tableData"
|
border
|
v-loading="tableLoading"
|
@selection-change="handleSelectionChange"
|
style="width: 100%"
|
height="calc(100vh - 21.5em)">
|
<el-table-column align="center"
|
type="selection"
|
:selectable="isDraft"
|
width="55" />
|
<el-table-column align="center"
|
label="序号"
|
type="index"
|
width="60" />
|
<el-table-column label="委外订单号"
|
prop="orderNo"
|
min-width="160"
|
show-overflow-tooltip />
|
<el-table-column label="合作商"
|
prop="partnerName"
|
min-width="180"
|
show-overflow-tooltip />
|
<el-table-column label="项目名称"
|
prop="projectName"
|
min-width="140"
|
show-overflow-tooltip />
|
<el-table-column label="申请日期"
|
prop="applyDate"
|
min-width="110"
|
show-overflow-tooltip />
|
<el-table-column label="预计交付日期"
|
prop="expectedDeliveryDate"
|
min-width="120"
|
show-overflow-tooltip />
|
<el-table-column label="合同金额(元)"
|
prop="contractAmount"
|
min-width="120"
|
align="right">
|
<template #default="scope">
|
{{ formatAmount(scope.row.contractAmount) }}
|
</template>
|
</el-table-column>
|
<el-table-column label="付款方式"
|
prop="paymentMethod"
|
min-width="100"
|
show-overflow-tooltip />
|
<el-table-column label="状态"
|
prop="status"
|
align="center"
|
width="100">
|
<template #default="scope">
|
<el-tag :type="statusTagType(scope.row.status)"
|
size="small">
|
{{ statusLabel(scope.row.status) }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column label="确认时间"
|
prop="confirmTime"
|
min-width="160"
|
show-overflow-tooltip />
|
<el-table-column label="作废原因"
|
prop="cancelReason"
|
min-width="140"
|
show-overflow-tooltip />
|
<el-table-column label="创建时间"
|
prop="createTime"
|
min-width="160"
|
show-overflow-tooltip />
|
<el-table-column fixed="right"
|
label="操作"
|
width="220"
|
align="center">
|
<template #default="scope">
|
<el-button link
|
type="primary"
|
@click="openForm('view', scope.row)">详情</el-button>
|
<el-button v-if="scope.row.status === 0"
|
link
|
type="primary"
|
@click="openForm('edit', scope.row)">编辑</el-button>
|
<el-button v-if="scope.row.status === 0"
|
link
|
type="primary"
|
@click="handleSubmitOrder(scope.row)">提交</el-button>
|
<el-button v-if="scope.row.status === 1"
|
link
|
type="primary"
|
@click="handleCompleteOrder(scope.row)">完成</el-button>
|
<el-button v-if="scope.row.status === 0 || scope.row.status === 1"
|
link
|
type="danger"
|
@click="handleCancelOrder(scope.row)">作废</el-button>
|
</template>
|
</el-table-column>
|
</el-table>
|
<pagination v-show="total > 0"
|
:total="total"
|
layout="total, sizes, prev, pager, next, jumper"
|
:page="page.current"
|
:limit="page.size"
|
@pagination="paginationChange" />
|
</div>
|
<el-dialog v-model="dialogFormVisible"
|
:title="dialogTitle"
|
width="90%"
|
top="5vh"
|
:close-on-click-modal="false"
|
@close="closeDia">
|
<el-form :model="form"
|
label-width="130px"
|
label-position="top"
|
:rules="rules"
|
ref="formRef"
|
:disabled="isView">
|
<el-row :gutter="30">
|
<el-col :span="8">
|
<el-form-item label="合作商:"
|
prop="partnerId">
|
<el-select v-model="form.partnerId"
|
placeholder="请选择"
|
clearable
|
filterable
|
style="width: 100%">
|
<el-option v-for="item in partnerOptions"
|
:key="item.id"
|
:label="item.partnerName"
|
:value="item.id" />
|
</el-select>
|
</el-form-item>
|
</el-col>
|
<el-col :span="8">
|
<el-form-item label="项目名称:"
|
prop="projectName">
|
<el-input v-model="form.projectName"
|
placeholder="请输入"
|
clearable />
|
</el-form-item>
|
</el-col>
|
<el-col :span="8">
|
<el-form-item label="付款方式:"
|
prop="paymentMethod">
|
<el-input v-model="form.paymentMethod"
|
placeholder="请输入"
|
clearable />
|
</el-form-item>
|
</el-col>
|
</el-row>
|
<el-row :gutter="30">
|
<el-col :span="8">
|
<el-form-item label="申请日期:"
|
prop="applyDate">
|
<el-date-picker v-model="form.applyDate"
|
type="date"
|
value-format="YYYY-MM-DD"
|
format="YYYY-MM-DD"
|
placeholder="请选择"
|
style="width: 100%" />
|
</el-form-item>
|
</el-col>
|
<el-col :span="8">
|
<el-form-item label="预计交付日期:"
|
prop="expectedDeliveryDate">
|
<el-date-picker v-model="form.expectedDeliveryDate"
|
type="date"
|
value-format="YYYY-MM-DD"
|
format="YYYY-MM-DD"
|
placeholder="请选择"
|
style="width: 100%" />
|
</el-form-item>
|
</el-col>
|
<el-col :span="8">
|
<el-form-item label="合同金额(元)">
|
<el-input :model-value="formatAmount(totalAmount)"
|
readonly />
|
</el-form-item>
|
</el-col>
|
</el-row>
|
<el-row :gutter="30">
|
<el-col :span="24">
|
<el-form-item label="备注:"
|
prop="remarks">
|
<el-input v-model="form.remarks"
|
type="textarea"
|
:rows="2"
|
placeholder="请输入"
|
clearable />
|
</el-form-item>
|
</el-col>
|
</el-row>
|
</el-form>
|
<div class="detail-header">
|
<span class="detail-title">产品明细</span>
|
<el-button v-if="!isView"
|
type="primary"
|
size="small"
|
@click="openScrapSelect">选报废品</el-button>
|
<el-button v-if="!isView"
|
size="small"
|
@click="addEmptyDetail">新增行</el-button>
|
</div>
|
<el-table :data="form.productData"
|
border
|
size="small"
|
style="width: 100%">
|
<el-table-column align="center"
|
label="序号"
|
type="index"
|
width="55" />
|
<el-table-column label="产品大类"
|
prop="productCategory"
|
min-width="120"
|
show-overflow-tooltip />
|
<el-table-column label="规格型号"
|
prop="specificationModel"
|
min-width="110"
|
show-overflow-tooltip />
|
<el-table-column label="单位"
|
prop="unit"
|
min-width="70" />
|
<el-table-column label="数量"
|
prop="quantity"
|
min-width="110">
|
<template #default="scope">
|
<el-input-number v-if="!isView"
|
v-model="scope.row.quantity"
|
:min="0"
|
:precision="4"
|
:step="1"
|
style="width: 100%" />
|
<span v-else>{{ scope.row.quantity }}</span>
|
</template>
|
</el-table-column>
|
<el-table-column label="税率(%)"
|
prop="taxRate"
|
min-width="110">
|
<template #default="scope">
|
<el-input-number v-if="!isView"
|
v-model="scope.row.taxRate"
|
:min="0"
|
:max="100"
|
:precision="2"
|
:step="1"
|
style="width: 100%" />
|
<span v-else>{{ scope.row.taxRate }}</span>
|
</template>
|
</el-table-column>
|
<el-table-column label="含税单价(元)"
|
prop="taxInclusiveUnitPrice"
|
min-width="130">
|
<template #default="scope">
|
<el-input-number v-if="!isView"
|
v-model="scope.row.taxInclusiveUnitPrice"
|
:min="0"
|
:precision="2"
|
:step="0.01"
|
style="width: 100%" />
|
<span v-else>{{ scope.row.taxInclusiveUnitPrice }}</span>
|
</template>
|
</el-table-column>
|
<el-table-column label="含税总价(元)"
|
prop="taxInclusiveTotalPrice"
|
min-width="120"
|
align="right">
|
<template #default="scope">
|
{{ formatAmount(lineTotal(scope.row)) }}
|
</template>
|
</el-table-column>
|
<el-table-column label="报废品"
|
prop="isScrap"
|
align="center"
|
width="80">
|
<template #default="scope">
|
<el-tag :type="scope.row.isScrap ? 'warning' : 'info'"
|
size="small">
|
{{ scope.row.isScrap ? "是" : "否" }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column label="批号"
|
prop="batchNo"
|
min-width="130"
|
show-overflow-tooltip />
|
<el-table-column label="可用量"
|
prop="availableQuantity"
|
min-width="100"
|
align="right" />
|
<el-table-column label="备注"
|
prop="remark"
|
min-width="130">
|
<template #default="scope">
|
<el-input v-if="!isView"
|
v-model="scope.row.remark"
|
placeholder="请输入"
|
clearable />
|
<span v-else>{{ scope.row.remark }}</span>
|
</template>
|
</el-table-column>
|
<el-table-column v-if="!isView"
|
fixed="right"
|
label="操作"
|
width="70"
|
align="center">
|
<template #default="scope">
|
<el-button link
|
type="danger"
|
@click="removeDetail(scope.$index)">删除</el-button>
|
</template>
|
</el-table-column>
|
</el-table>
|
<template #footer>
|
<div class="dialog-footer">
|
<el-button v-if="!isView"
|
type="primary"
|
@click="submitForm">确认</el-button>
|
<el-button @click="closeDia">{{ isView ? "关闭" : "取消" }}</el-button>
|
</div>
|
</template>
|
</el-dialog>
|
<!-- 报废品选料(只读,不扣库存、不占用) -->
|
<el-dialog v-model="scrapDialogVisible"
|
title="选择报废品"
|
width="70%"
|
append-to-body>
|
<el-form :model="scrapSearch"
|
:inline="true">
|
<el-form-item label="产品名称:">
|
<el-input v-model="scrapSearch.productName"
|
placeholder="请输入"
|
clearable
|
style="width: 160px" />
|
</el-form-item>
|
<el-form-item label="批号:">
|
<el-input v-model="scrapSearch.batchNo"
|
placeholder="请输入"
|
clearable
|
style="width: 160px" />
|
</el-form-item>
|
<el-form-item>
|
<el-button type="primary"
|
@click="handleScrapQuery">搜索</el-button>
|
</el-form-item>
|
</el-form>
|
<el-table :data="scrapTableData"
|
border
|
v-loading="scrapLoading"
|
highlight-current-row
|
style="width: 100%"
|
height="360px"
|
@current-change="handleScrapCurrentChange">
|
<el-table-column align="center"
|
label="序号"
|
type="index"
|
width="60" />
|
<el-table-column label="产品名称"
|
prop="productName"
|
min-width="140"
|
show-overflow-tooltip />
|
<el-table-column label="规格型号"
|
prop="model"
|
min-width="120"
|
show-overflow-tooltip />
|
<el-table-column label="批号"
|
prop="batchNo"
|
min-width="140"
|
show-overflow-tooltip />
|
<el-table-column label="单位"
|
prop="unit"
|
min-width="70" />
|
<el-table-column label="库存数量"
|
prop="qualitity"
|
min-width="100"
|
align="right" />
|
<el-table-column label="锁定数量"
|
prop="lockedQuantity"
|
min-width="100"
|
align="right" />
|
<el-table-column label="可用数量"
|
prop="unLockedQuantity"
|
min-width="100"
|
align="right" />
|
<el-table-column label="备注"
|
prop="remark"
|
min-width="120"
|
show-overflow-tooltip />
|
</el-table>
|
<pagination v-show="scrapTotal > 0"
|
:total="scrapTotal"
|
layout="total, sizes, prev, pager, next, jumper"
|
:page="scrapPage.current"
|
:limit="scrapPage.size"
|
@pagination="scrapPaginationChange" />
|
<template #footer>
|
<div class="dialog-footer">
|
<el-button type="primary"
|
@click="confirmScrapSelect">确认</el-button>
|
<el-button @click="scrapDialogVisible = false">取消</el-button>
|
</div>
|
</template>
|
</el-dialog>
|
</div>
|
</template>
|
|
<script setup>
|
import { ref, reactive, computed, toRefs, getCurrentInstance, onMounted } from "vue";
|
import pagination from "@/components/PIMTable/Pagination.vue";
|
import { ElMessageBox } from "element-plus";
|
import {
|
listOutsourcingOrder,
|
getOutsourcingOrder,
|
addOutsourcingOrder,
|
editOutsourcingOrder,
|
delOutsourcingOrder,
|
submitOutsourcingOrder,
|
completeOutsourcingOrder,
|
cancelOutsourcingOrder,
|
exportOutsourcingOrder,
|
scrapStockPage,
|
} from "@/api/outsourcing/order.js";
|
import { getPartnerOptions } from "@/api/outsourcing/partner.js";
|
|
const { proxy } = getCurrentInstance();
|
const tableData = ref([]);
|
const selectedRows = ref([]);
|
const tableLoading = ref(false);
|
const dialogFormVisible = ref(false);
|
const operationType = ref("");
|
const partnerOptions = ref([]);
|
const dateRange = ref([]);
|
const page = reactive({
|
current: 1,
|
size: 10,
|
});
|
const total = ref(0);
|
|
const statusOptions = [
|
{ label: "草稿", value: 0 },
|
{ label: "已确认", value: 1 },
|
{ label: "已完成", value: 2 },
|
{ label: "已作废", value: 3 },
|
];
|
|
const statusLabelMap = {
|
0: "草稿",
|
1: "已确认",
|
2: "已完成",
|
3: "已作废",
|
};
|
|
const statusTagMap = {
|
0: "info",
|
1: "primary",
|
2: "success",
|
3: "danger",
|
};
|
|
const statusLabel = status => statusLabelMap[status] ?? status;
|
const statusTagType = status => statusTagMap[status] || "info";
|
|
const data = reactive({
|
searchForm: {
|
orderNo: "",
|
partnerId: "",
|
projectName: "",
|
status: "",
|
},
|
form: {},
|
rules: {
|
partnerId: [{ required: true, message: "请选择合作商", trigger: "change" }],
|
projectName: [{ required: true, message: "请输入项目名称", trigger: "blur" }],
|
applyDate: [{ required: true, message: "请选择申请日期", trigger: "change" }],
|
},
|
});
|
const { searchForm, form, rules } = toRefs(data);
|
|
const isView = computed(() => operationType.value === "view");
|
const isDraft = row => row.status === 0;
|
const dialogTitle = computed(() => {
|
if (operationType.value === "add") {
|
return "新增委外订单";
|
}
|
return operationType.value === "edit" ? "编辑委外订单" : "委外订单详情";
|
});
|
|
const buildEmptyForm = () => ({
|
id: null,
|
partnerId: undefined,
|
projectName: "",
|
applyDate: today(),
|
expectedDeliveryDate: "",
|
paymentMethod: "",
|
remarks: "",
|
productData: [],
|
});
|
|
function today() {
|
const d = new Date();
|
const month = String(d.getMonth() + 1).padStart(2, "0");
|
const day = String(d.getDate()).padStart(2, "0");
|
return `${d.getFullYear()}-${month}-${day}`;
|
}
|
|
const formatAmount = value => {
|
const num = Number(value);
|
return Number.isFinite(num) ? num.toFixed(2) : "0.00";
|
};
|
|
// 含税总价由数量 × 含税单价得出,后端会按明细合计覆盖 contractAmount
|
const lineTotal = row => {
|
const quantity = Number(row?.quantity) || 0;
|
const price = Number(row?.taxInclusiveUnitPrice) || 0;
|
return Math.round(quantity * price * 100) / 100;
|
};
|
|
const totalAmount = computed(() =>
|
(form.value.productData || []).reduce((sum, row) => sum + lineTotal(row), 0)
|
);
|
|
// 去掉空值,避免 status='' 这类空串被后端当成 0(草稿)解析
|
const compact = obj =>
|
Object.fromEntries(
|
Object.entries(obj).filter(([, v]) => v !== "" && v !== null && v !== undefined)
|
);
|
|
const getList = () => {
|
tableLoading.value = true;
|
const [startDate, endDate] = dateRange.value || [];
|
listOutsourcingOrder({
|
pageNum: page.current,
|
pageSize: page.size,
|
...compact(searchForm.value),
|
startDate,
|
endDate,
|
})
|
.then(res => {
|
tableLoading.value = false;
|
// 委外订单列表返回的是 RuoYi 结构,行在顶层 rows
|
tableData.value = res.rows || [];
|
total.value = res.total || 0;
|
})
|
.catch(() => {
|
tableLoading.value = false;
|
});
|
};
|
|
const handleQuery = () => {
|
page.current = 1;
|
getList();
|
};
|
|
const resetSearch = () => {
|
searchForm.value = { orderNo: "", partnerId: "", projectName: "", status: "" };
|
dateRange.value = [];
|
handleQuery();
|
};
|
|
const paginationChange = obj => {
|
page.current = obj.page;
|
page.size = obj.limit;
|
getList();
|
};
|
|
const handleSelectionChange = selection => {
|
selectedRows.value = selection;
|
};
|
|
const openForm = (type, row) => {
|
operationType.value = type;
|
form.value = buildEmptyForm();
|
proxy.resetForm("formRef");
|
dialogFormVisible.value = true;
|
if (type !== "add" && row) {
|
getOutsourcingOrder(row.id).then(res => {
|
const detail = res.data || {};
|
form.value = {
|
...buildEmptyForm(),
|
...detail,
|
productData: (detail.productData || []).map(item => ({ ...item })),
|
};
|
});
|
}
|
};
|
|
const addEmptyDetail = () => {
|
form.value.productData.push({
|
productId: undefined,
|
productModelId: undefined,
|
productCategory: "",
|
specificationModel: "",
|
unit: "",
|
quantity: undefined,
|
taxRate: undefined,
|
taxInclusiveUnitPrice: undefined,
|
taxInclusiveTotalPrice: undefined,
|
isScrap: false,
|
stockInventoryId: undefined,
|
batchNo: "",
|
availableQuantity: undefined,
|
remark: "",
|
});
|
};
|
|
const removeDetail = index => {
|
form.value.productData.splice(index, 1);
|
};
|
|
const submitForm = () => {
|
proxy.$refs["formRef"].validate(valid => {
|
if (!valid) {
|
return;
|
}
|
if (!form.value.productData.length) {
|
proxy.$modal.msgWarning("请至少添加一条产品明细");
|
return;
|
}
|
// 只提交文档约定的字段:单号/状态/确认时间/合同金额/合作商名称等由后端维护
|
const payload = {
|
partnerId: form.value.partnerId,
|
projectName: form.value.projectName,
|
applyDate: form.value.applyDate,
|
expectedDeliveryDate: form.value.expectedDeliveryDate,
|
paymentMethod: form.value.paymentMethod,
|
remarks: form.value.remarks,
|
productData: form.value.productData.map(row => ({
|
productId: row.productId,
|
productModelId: row.productModelId,
|
productCategory: row.productCategory,
|
specificationModel: row.specificationModel,
|
unit: row.unit,
|
quantity: row.quantity,
|
taxRate: row.taxRate,
|
taxInclusiveUnitPrice: row.taxInclusiveUnitPrice,
|
taxInclusiveTotalPrice: lineTotal(row),
|
isScrap: !!row.isScrap,
|
stockInventoryId: row.stockInventoryId,
|
batchNo: row.batchNo,
|
availableQuantity: row.availableQuantity,
|
remark: row.remark,
|
})),
|
...(form.value.id ? { id: form.value.id } : {}),
|
};
|
const api = form.value.id ? editOutsourcingOrder : addOutsourcingOrder;
|
api(payload).then(() => {
|
proxy.$modal.msgSuccess("操作成功");
|
closeDia();
|
getList();
|
});
|
});
|
};
|
|
const closeDia = () => {
|
proxy.resetForm("formRef");
|
dialogFormVisible.value = false;
|
};
|
|
const handleSubmitOrder = row => {
|
ElMessageBox.confirm(
|
`是否确认提交订单 ${row.orderNo}?提交后将占用所选报废品批次的可用量,需到出库管理审批通过后才能完成订单。`,
|
"提交",
|
{
|
confirmButtonText: "确认",
|
cancelButtonText: "取消",
|
type: "warning",
|
}
|
)
|
.then(() => {
|
submitOutsourcingOrder(row.id).then(() => {
|
proxy.$modal.msgSuccess("提交成功");
|
getList();
|
});
|
})
|
.catch(() => {
|
proxy.$modal.msg("已取消");
|
});
|
};
|
|
const handleCompleteOrder = row => {
|
ElMessageBox.confirm(`是否确认完成订单 ${row.orderNo}?`, "完成", {
|
confirmButtonText: "确认",
|
cancelButtonText: "取消",
|
type: "warning",
|
})
|
.then(() => {
|
completeOutsourcingOrder(row.id).then(() => {
|
proxy.$modal.msgSuccess("操作成功");
|
getList();
|
});
|
})
|
.catch(() => {
|
proxy.$modal.msg("已取消");
|
});
|
};
|
|
const handleCancelOrder = row => {
|
ElMessageBox.prompt("请输入作废原因(可不填)", `作废订单 ${row.orderNo}`, {
|
confirmButtonText: "确认作废",
|
cancelButtonText: "取消",
|
inputPlaceholder: "作废原因",
|
})
|
.then(({ value }) => {
|
cancelOutsourcingOrder(row.id, value || "").then(() => {
|
proxy.$modal.msgSuccess("作废成功");
|
getList();
|
});
|
})
|
.catch(() => {
|
proxy.$modal.msg("已取消");
|
});
|
};
|
|
const handleBatchDelete = () => {
|
if (selectedRows.value.length === 0) {
|
proxy.$modal.msgWarning("请选择数据");
|
return;
|
}
|
const ids = selectedRows.value.map(item => item.id);
|
ElMessageBox.confirm("选中的内容将被删除,是否确认删除?仅草稿状态允许删除。", "删除", {
|
confirmButtonText: "确认",
|
cancelButtonText: "取消",
|
type: "warning",
|
})
|
.then(() => {
|
delOutsourcingOrder(ids).then(() => {
|
proxy.$modal.msgSuccess("删除成功");
|
getList();
|
});
|
})
|
.catch(() => {
|
proxy.$modal.msg("已取消");
|
});
|
};
|
|
const saveExcelBlob = (blobData, filename) => {
|
const blob = new Blob([blobData], {
|
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
});
|
const url = window.URL.createObjectURL(blob);
|
const link = document.createElement("a");
|
link.href = url;
|
link.download = filename;
|
document.body.appendChild(link);
|
link.click();
|
setTimeout(() => {
|
document.body.removeChild(link);
|
window.URL.revokeObjectURL(url);
|
}, 100);
|
};
|
|
const handleExport = () => {
|
ElMessageBox.confirm("是否确认导出?", "导出", {
|
confirmButtonText: "确认",
|
cancelButtonText: "取消",
|
type: "warning",
|
})
|
.then(() => {
|
const [startDate, endDate] = dateRange.value || [];
|
exportOutsourcingOrder({
|
...compact(searchForm.value),
|
startDate,
|
endDate,
|
}).then(res => {
|
saveExcelBlob(res, "委外订单.xlsx");
|
});
|
})
|
.catch(() => {
|
proxy.$modal.msg("已取消");
|
});
|
};
|
|
// 报废品选料:只读带出,不扣库存、不占用
|
const scrapDialogVisible = ref(false);
|
const scrapLoading = ref(false);
|
const scrapTableData = ref([]);
|
const scrapSelectedRow = ref(null);
|
const scrapTotal = ref(0);
|
const scrapPage = reactive({ current: 1, size: 10 });
|
const scrapSearch = reactive({ productName: "", batchNo: "" });
|
|
const getScrapList = () => {
|
scrapLoading.value = true;
|
scrapStockPage({
|
pageNum: scrapPage.current,
|
pageSize: scrapPage.size,
|
productName: scrapSearch.productName || undefined,
|
batchNo: scrapSearch.batchNo || undefined,
|
})
|
.then(res => {
|
scrapLoading.value = false;
|
scrapTableData.value = res.data?.records || [];
|
scrapTotal.value = res.data?.total || 0;
|
})
|
.catch(() => {
|
scrapLoading.value = false;
|
});
|
};
|
|
const openScrapSelect = () => {
|
scrapSelectedRow.value = null;
|
scrapSearch.productName = "";
|
scrapSearch.batchNo = "";
|
scrapPage.current = 1;
|
scrapDialogVisible.value = true;
|
getScrapList();
|
};
|
|
const handleScrapQuery = () => {
|
scrapPage.current = 1;
|
getScrapList();
|
};
|
|
const scrapPaginationChange = obj => {
|
scrapPage.current = obj.page;
|
scrapPage.size = obj.limit;
|
getScrapList();
|
};
|
|
const handleScrapCurrentChange = row => {
|
scrapSelectedRow.value = row;
|
};
|
|
const confirmScrapSelect = () => {
|
const row = scrapSelectedRow.value;
|
if (!row) {
|
proxy.$modal.msgWarning("请选择一条报废品批次");
|
return;
|
}
|
form.value.productData.push({
|
productId: row.productId,
|
productModelId: row.productModelId,
|
productCategory: row.productName || "",
|
specificationModel: row.model || "",
|
unit: row.unit || "",
|
quantity: undefined,
|
taxRate: undefined,
|
taxInclusiveUnitPrice: undefined,
|
taxInclusiveTotalPrice: undefined,
|
isScrap: true,
|
stockInventoryId: row.id,
|
batchNo: row.batchNo || "",
|
availableQuantity: row.unLockedQuantity,
|
remark: "",
|
});
|
scrapDialogVisible.value = false;
|
};
|
|
onMounted(() => {
|
getList();
|
getPartnerOptions().then(res => {
|
partnerOptions.value = res.data || [];
|
});
|
});
|
</script>
|
|
<style scoped lang="scss">
|
.search_form {
|
margin-bottom: 16px;
|
}
|
|
.actions {
|
display: flex;
|
justify-content: flex-end;
|
margin-bottom: 12px;
|
}
|
|
.detail-header {
|
display: flex;
|
align-items: center;
|
gap: 12px;
|
margin: 8px 0 12px;
|
|
.detail-title {
|
flex: 1;
|
font-size: 15px;
|
font-weight: 600;
|
color: #1d6fd8;
|
}
|
}
|
</style>
|