From 9646ba4b026e4dbee0c0d5ac3d52b428bfef7b29 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期五, 28 八月 2026 10:49:44 +0800
Subject: [PATCH] 新疆-新聚 1.销售台账中的销售合同按框架合同处理 2.设备台账需按车间/区域汇总设备,车间/位置可自行新增,且支持子父级递归 3.计量器具台账支持通过 Excel 文件批量新增数据 4.设备保养定时任务新增“年度保养”任务频率
---
src/views/salesManagement/salesLedger/index.vue | 284 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 262 insertions(+), 22 deletions(-)
diff --git a/src/views/salesManagement/salesLedger/index.vue b/src/views/salesManagement/salesLedger/index.vue
index 610c17c..ccf90b4 100644
--- a/src/views/salesManagement/salesLedger/index.vue
+++ b/src/views/salesManagement/salesLedger/index.vue
@@ -177,7 +177,7 @@
<el-button
link
type="primary"
- :disabled="!canShip(scope.row)"
+ :disabled="!canShip(scope.row) || props.row.contractType === 2"
@click="openDeliveryForm(scope.row)"
>
鍙戣揣
@@ -261,7 +261,7 @@
width="200"
show-overflow-tooltip
/>
- <el-table-column fixed="right" label="鎿嶄綔" width="220" align="center">
+ <el-table-column fixed="right" label="鎿嶄綔" width="320" align="center">
<template #default="scope">
<el-button link type="primary" @click="openForm('view', scope.row)"
>璇︽儏
@@ -276,6 +276,20 @@
!canEditLedger(scope.row)
"
>缂栬緫
+ </el-button>
+ <el-button
+ v-if="scope.row.contractType === 2"
+ link
+ type="success"
+ @click="openFrameworkOrderDialog(scope.row)"
+ >鍒涘缓妗嗘灦璁㈠崟
+ </el-button>
+ <el-button
+ v-if="scope.row.contractType === 2"
+ link
+ type="primary"
+ @click="openFrameworkOrderList(scope.row)"
+ >妗嗘灦璁㈠崟
</el-button>
<el-button link type="primary" @click="openFileDialog(scope.row)"
>闄勪欢
@@ -320,6 +334,21 @@
<el-button type="primary" plain @click="openQuotationDialog">
浠庨攢鍞姤浠峰鍏�
</el-button>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍚堝悓绫诲瀷锛�" prop="contractType">
+ <el-select
+ v-model="form.contractType"
+ placeholder="璇烽�夋嫨"
+ clearable
+ :disabled="operationType === 'view' || operationType === 'edit'"
+ >
+ <el-option label="鏅�氶攢鍞悎鍚�" :value="1" />
+ <el-option label="妗嗘灦鍚堝悓" :value="2" />
+ </el-select>
+ </el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
@@ -467,7 +496,7 @@
</el-form-item>
</el-col>
</el-row>
- <el-row :gutter="30">
+ <el-row :gutter="30" v-if="!isFrameworkContract">
<el-col :span="12">
<el-form-item label="浜よ揣鏃ユ湡锛�" prop="entryDate">
<el-date-picker
@@ -750,7 +779,7 @@
/>
</el-form-item>
</el-col>
- <el-col :span="12">
+ <el-col :span="12" v-if="!isFrameworkContract">
<el-form-item label="绋庣巼(%)锛�" prop="taxRate">
<el-select
v-model="productForm.taxRate"
@@ -783,7 +812,7 @@
/>
</el-form-item>
</el-col>
- <el-col :span="12">
+ <el-col :span="12" v-if="!isFrameworkContract">
<el-form-item label="鏁伴噺锛�" prop="quantity">
<el-input-number
:step="0.1"
@@ -799,7 +828,7 @@
</el-col>
</el-row>
<el-row :gutter="30">
- <el-col :span="12">
+ <el-col :span="12" v-if="!isFrameworkContract">
<el-form-item label="鍚◣鎬讳环(鍏�)锛�" prop="taxInclusiveTotalPrice">
<el-input
v-model="productForm.taxInclusiveTotalPrice"
@@ -809,7 +838,7 @@
/>
</el-form-item>
</el-col>
- <el-col :span="12">
+ <el-col :span="12" v-if="!isFrameworkContract">
<el-form-item
label="涓嶅惈绋庢�讳环(鍏�)锛�"
prop="taxExclusiveTotalPrice"
@@ -824,7 +853,7 @@
</el-col>
</el-row>
<el-row :gutter="30">
- <el-col :span="12">
+ <el-col :span="12" v-if="!isFrameworkContract">
<el-form-item label="鍙戠エ绫诲瀷锛�" prop="invoiceType">
<el-select
v-model="productForm.invoiceType"
@@ -836,7 +865,7 @@
</el-select>
</el-form-item>
</el-col>
- <el-col :span="12">
+ <el-col :span="12" v-if="!isFrameworkContract">
<el-form-item label="鏄惁鐢熶骇锛�" prop="isProduction">
<el-radio-group v-model="productForm.isProduction">
<el-radio label="鏄�" :value="true" />
@@ -1177,6 +1206,104 @@
</div>
</template>
</el-dialog>
+ <!-- 鍒涘缓妗嗘灦璁㈠崟寮圭獥 -->
+ <el-dialog
+ v-model="frameworkOrderDialogVisible"
+ title="鍒涘缓妗嗘灦璁㈠崟"
+ width="70%"
+ :close-on-click-modal="false"
+ >
+ <el-form label-width="120px" label-position="top">
+ <el-form-item label="鐖舵鏋跺悎鍚岋細">
+ <el-input
+ :model-value="currentFrameworkContract?.salesContractNo"
+ disabled
+ />
+ </el-form-item>
+ <el-form-item label="澶囨敞锛�">
+ <el-input
+ v-model="frameworkOrderForm.remarks"
+ type="textarea"
+ :rows="2"
+ placeholder="璇疯緭鍏ュ娉�"
+ />
+ </el-form-item>
+ <el-form-item label="浜у搧锛堝~鍐欎氦璐ф棩鏈燂級锛�">
+ <el-table :data="frameworkOrderProducts" border>
+ <el-table-column label="浜у搧澶х被" prop="productCategory" />
+ <el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" />
+ <el-table-column label="鍗曚綅" prop="unit" />
+ <el-table-column label="浜よ揣鏃ユ湡" align="center">
+ <template #default="scope">
+ <el-date-picker
+ v-model="scope.row.deliveryDate"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨"
+ clearable
+ />
+ </template>
+ </el-table-column>
+ </el-table>
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <el-button type="primary" @click="submitFrameworkOrder"
+ >纭鍒涘缓
+ </el-button>
+ <el-button @click="frameworkOrderDialogVisible = false">鍙栨秷</el-button>
+ </template>
+ </el-dialog>
+ <!-- 妗嗘灦璁㈠崟鍒楄〃寮圭獥 -->
+ <el-dialog
+ v-model="frameworkOrderListVisible"
+ title="妗嗘灦璁㈠崟鍒楄〃"
+ width="80%"
+ :close-on-click-modal="false"
+ >
+ <el-alert
+ v-if="frameworkContractShippedQty !== null"
+ type="info"
+ :closable="false"
+ style="margin-bottom: 12px"
+ :title="'鐖舵鏋跺悎鍚岀疮璁″凡鍙戣揣鏁伴噺锛�' + frameworkContractShippedQty"
+ />
+ <el-table :data="frameworkOrderList" border :row-key="(row) => row.id">
+ <el-table-column type="expand">
+ <template #default="props">
+ <el-table :data="props.row.products" border size="small">
+ <el-table-column label="浜у搧澶х被" prop="productCategory" />
+ <el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" />
+ <el-table-column label="鍗曚綅" prop="unit" />
+ <el-table-column label="鎿嶄綔" width="80" align="center">
+ <template #default="scope">
+ <el-button
+ link
+ type="primary"
+ @click="shipFrameworkOrderProduct(scope.row, props.row)"
+ >鍙戣揣
+ </el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ </template>
+ </el-table-column>
+ <el-table-column
+ label="璁㈠崟缂栧彿"
+ prop="salesContractNo"
+ min-width="180"
+ />
+ <el-table-column label="椤圭洰鍚嶇О" prop="projectName" min-width="160" />
+ <el-table-column label="澶囨敞" prop="remarks" min-width="160" />
+ <el-table-column
+ label="绱鍙戣揣鏁伴噺"
+ prop="shippedQuantity"
+ width="140"
+ align="center"
+ />
+ </el-table>
+ </el-dialog>
</div>
</template>
@@ -1201,6 +1328,9 @@
delProduct,
delLedgerFile,
getProductInventory,
+ createFrameworkOrder,
+ listFrameworkOrders,
+ frameworkContractShippedQuantity,
} from "@/api/salesManagement/salesLedger.js";
import { getStockInventoryByModelId } from "@/api/inventoryManagement/stockInventory.js";
import { modelList, productTreeList } from "@/api/basicData/product.js";
@@ -1250,6 +1380,7 @@
},
form: {
salesContractNo: "",
+ contractType: 2,
autoGenerateContractNo: true,
salesman: "",
customerId: "",
@@ -1267,11 +1398,31 @@
customerId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
entryPerson: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
entryDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- deliveryDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ deliveryDate: [
+ {
+ validator: (rule, value, callback) => {
+ if (form.value.contractType === 2) return callback();
+ if (!value) return callback(new Error("璇烽�夋嫨"));
+ callback();
+ },
+ trigger: "change",
+ },
+ ],
executionDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
},
});
const { form, rules } = toRefs(data);
+const isFrameworkContract = computed(() => form.value.contractType === 2);
+const frameworkOptional = (message, trigger = "blur") => ({
+ validator: (_rule, value, callback) => {
+ if (isFrameworkContract.value) return callback();
+ if (value === undefined || value === null || value === "") {
+ return callback(new Error(message));
+ }
+ callback();
+ },
+ trigger,
+});
const { form: searchForm } = useFormData(data.searchForm);
// 浜у搧琛ㄥ崟寮规鏁版嵁
const productFormVisible = ref(false);
@@ -1297,18 +1448,12 @@
{ required: true, message: "璇烽�夋嫨", trigger: "change" },
],
unit: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- quantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- taxInclusiveUnitPrice: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
- ],
- taxRate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- taxInclusiveTotalPrice: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
- ],
- taxExclusiveTotalPrice: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
- ],
- invoiceType: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ quantity: [frameworkOptional("璇疯緭鍏�")],
+ taxInclusiveUnitPrice: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ taxRate: [frameworkOptional("璇烽�夋嫨", "change")],
+ taxInclusiveTotalPrice: [frameworkOptional("璇疯緭鍏�")],
+ taxExclusiveTotalPrice: [frameworkOptional("璇疯緭鍏�")],
+ invoiceType: [frameworkOptional("璇烽�夋嫨", "change")],
isProduction: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
},
});
@@ -1740,6 +1885,7 @@
form.value.entryPerson = userStore.id;
if (type === "add") {
// 鏂板鏃惰缃綍鍏ユ棩鏈熶负褰撳ぉ
+ form.value.contractType = 2;
form.value.entryDate = getCurrentDate();
// 绛捐鏃ユ湡榛樿涓哄綋澶�
form.value.executionDate = getCurrentDate();
@@ -1892,6 +2038,14 @@
}
form.value.storageBlobDTOs = fileList;
form.value.type = 1;
+ if (isFrameworkContract.value) {
+ form.value.productData = form.value.productData.map((item) => ({
+ ...item,
+ quantity: null,
+ deliveryDate: null,
+ isProduction: false,
+ }));
+ }
if (form.value.autoGenerateContractNo) {
form.value.salesContractNo = "";
}
@@ -2933,6 +3087,92 @@
deliveryFormVisible.value = false;
currentDeliveryRow.value = null;
};
+
+// 妗嗘灦鍚堝悓 / 妗嗘灦璁㈠崟鐩稿叧
+const frameworkOrderDialogVisible = ref(false);
+const frameworkOrderListVisible = ref(false);
+const currentFrameworkContract = ref(null);
+const frameworkOrderForm = reactive({
+ remarks: "",
+});
+const frameworkOrderProducts = ref([]);
+const frameworkOrderList = ref([]);
+const frameworkContractShippedQty = ref(null);
+
+const openFrameworkOrderDialog = async (row) => {
+ currentFrameworkContract.value = row;
+ frameworkOrderForm.remarks = "";
+ frameworkOrderProducts.value = [];
+ try {
+ const res = await productList({ salesLedgerId: row.id, type: 1 });
+ frameworkOrderProducts.value = (res.data || []).map((p) => ({
+ parentProductId: p.id,
+ productCategory: p.productCategory,
+ specificationModel: p.specificationModel,
+ unit: p.unit,
+ deliveryDate: "",
+ }));
+ } catch (e) {
+ frameworkOrderProducts.value = [];
+ }
+ frameworkOrderDialogVisible.value = true;
+};
+
+const submitFrameworkOrder = async () => {
+ const selected = frameworkOrderProducts.value.filter((p) => p.deliveryDate);
+ if (selected.length === 0) {
+ proxy.$modal.msgWarning("璇疯嚦灏戜负涓�涓骇鍝佸~鍐欎氦璐ф棩鏈�");
+ return;
+ }
+ try {
+ await createFrameworkOrder({
+ id: currentFrameworkContract.value.id,
+ remarks: frameworkOrderForm.remarks,
+ productData: selected.map((p) => ({
+ parentProductId: p.parentProductId,
+ deliveryDate: p.deliveryDate,
+ })),
+ });
+ proxy.$modal.msgSuccess("妗嗘灦璁㈠崟鍒涘缓鎴愬姛");
+ frameworkOrderDialogVisible.value = false;
+ } catch (e) {
+ // 閿欒宸茬敱璇锋眰鎷︽埅鍣ㄧ粺涓�鎻愮ず
+ }
+};
+
+const openFrameworkOrderList = async (row) => {
+ currentFrameworkContract.value = row;
+ frameworkContractShippedQty.value = null;
+ frameworkOrderList.value = [];
+ frameworkOrderListVisible.value = true;
+ listFrameworkOrders({ parentContractId: row.id }).then(async (res) => {
+ const orders = res.data || [];
+ const withProducts = [];
+ for (const order of orders) {
+ let products = [];
+ try {
+ const productRes = await productList({ salesLedgerId: order.id, type: 1 });
+ products = productRes.data || [];
+ } catch (e) {
+ products = [];
+ }
+ withProducts.push({ ...order, products });
+ }
+ frameworkOrderList.value = withProducts;
+ });
+ frameworkContractShippedQuantity({ parentContractId: row.id }).then((res) => {
+ frameworkContractShippedQty.value = res.data ?? 0;
+ });
+};
+
+const shipFrameworkOrderProduct = (productRow, orderRow) => {
+ if (!orderRow || !orderRow.id) return;
+ frameworkOrderListVisible.value = false;
+ openDeliveryForm({
+ ...productRow,
+ salesLedgerId: orderRow.id,
+ });
+};
const currentFactoryName = ref("");
const getCurrentFactoryName = async () => {
let res = await userStore.getInfo();
--
Gitblit v1.9.3