From 4c8d18cc5ed8a7b0e220c91a858d16d0310896df Mon Sep 17 00:00:00 2001
From: zhangwencui <1064582902@qq.com>
Date: 星期一, 29 六月 2026 16:50:03 +0800
Subject: [PATCH] BOM新增修改删除功能开发、以及BOM结构的可编辑
---
src/pages/productionDesign/bom/index.vue | 365 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 364 insertions(+), 1 deletions(-)
diff --git a/src/pages/productionDesign/bom/index.vue b/src/pages/productionDesign/bom/index.vue
index 97ba5f6..c3368d8 100644
--- a/src/pages/productionDesign/bom/index.vue
+++ b/src/pages/productionDesign/bom/index.vue
@@ -57,6 +57,14 @@
size="small"
type="primary"
@click="goStructure(item)">鏌ョ湅璇︽儏</up-button>
+ <up-button class="action-btn"
+ size="small"
+ type="warning"
+ @click="openEdit(item)">淇敼</up-button>
+ <up-button class="action-btn"
+ size="small"
+ type="error"
+ @click="handleDelete(item)">鍒犻櫎</up-button>
</view>
</view>
<up-loadmore :status="pageStatus" />
@@ -66,13 +74,119 @@
<up-empty text="鏆傛棤BOM鏁版嵁"
mode="list"></up-empty>
</view>
+ <view class="fab-button"
+ @click="openAdd">
+ <up-icon name="plus"
+ size="24"
+ color="#ffffff"></up-icon>
+ </view>
+ <up-popup :show="showFormPopup"
+ mode="bottom"
+ round
+ @close="closeFormPopup">
+ <view class="popup-container">
+ <view class="popup-header">
+ <text class="popup-cancel"
+ @click="closeFormPopup">鍙栨秷</text>
+ <text class="popup-title">{{ formMode === 'add' ? '鏂板BOM' : '淇敼BOM' }}</text>
+ <text class="popup-confirm"
+ @click="submitForm">纭畾</text>
+ </view>
+ <view class="popup-body">
+ <up-form ref="bomFormRef"
+ :model="bomForm"
+ :rules="bomRules"
+ label-width="110">
+ <up-form-item label="浜у搧"
+ prop="productModelId"
+ required>
+ <up-input v-model="bomForm.productName"
+ readonly
+ placeholder="鐐瑰嚮閫夋嫨浜у搧"
+ @click="openProductPicker" />
+ <template #right>
+ <up-icon name="arrow-right"
+ @click="openProductPicker"></up-icon>
+ </template>
+ </up-form-item>
+ <up-form-item label="瑙勬牸鍨嬪彿">
+ <up-input v-model="bomForm.productModelName"
+ readonly
+ placeholder="--" />
+ </up-form-item>
+ <up-form-item label="鐗堟湰鍙�"
+ prop="version"
+ required>
+ <up-input v-model="bomForm.version"
+ placeholder="璇疯緭鍏ョ増鏈彿"
+ clearable />
+ </up-form-item>
+ <up-form-item label="澶囨敞"
+ prop="remark">
+ <up-textarea v-model="bomForm.remark"
+ placeholder="璇疯緭鍏ュ娉�"
+ auto-height />
+ </up-form-item>
+ </up-form>
+ </view>
+ </view>
+ </up-popup>
+ <up-popup :show="showProductPicker"
+ mode="bottom"
+ round
+ @close="showProductPicker = false">
+ <view class="popup-container">
+ <view class="popup-header">
+ <text class="popup-cancel"
+ @click="showProductPicker = false">鍙栨秷</text>
+ <text class="popup-title">閫夋嫨浜у搧</text>
+ <text class="popup-confirm"
+ @click="handleProductSearch">鎼滅储</text>
+ </view>
+ <view class="popup-body">
+ <view class="picker-search">
+ <up-input v-model="productQuery.productName"
+ placeholder="浜у搧鍚嶇О"
+ clearable
+ @change="handleProductSearch" />
+ <up-input v-model="productQuery.model"
+ placeholder="瑙勬牸鍨嬪彿"
+ clearable
+ @change="handleProductSearch" />
+ </view>
+ <scroll-view scroll-y
+ class="picker-list"
+ @scrolltolower="loadMoreProducts">
+ <view v-for="row in productList"
+ :key="row.id"
+ class="picker-item"
+ @click="selectProduct(row)">
+ <view class="picker-item__title">
+ <text>{{ row.productName || '-' }}</text>
+ </view>
+ <view class="picker-item__sub">
+ <text>{{ row.model || '-' }}</text>
+ <text class="picker-item__unit">{{ row.unit || '-' }}</text>
+ </view>
+ </view>
+ <up-loadmore :status="productPageStatus" />
+ </scroll-view>
+ </view>
+ </view>
+ </up-popup>
</view>
</template>
<script setup>
import { reactive, ref } from "vue";
import { onReachBottom, onShow } from "@dcloudio/uni-app";
- import { listPage } from "@/api/productionManagement/bom";
+ import {
+ listPage,
+ add,
+ update,
+ batchDelete,
+ getProductList,
+ } from "@/api/productionManagement/bom";
const queryParams = reactive({
productName: "",
@@ -85,6 +199,34 @@
size: 3,
total: 0,
});
+ const showFormPopup = ref(false);
+ const formMode = ref("add");
+ const bomFormRef = ref(null);
+ const bomForm = reactive({
+ id: undefined,
+ productName: "",
+ productModelName: "",
+ productModelId: "",
+ remark: "",
+ version: "",
+ });
+ const bomRules = {
+ productModelId: [{ required: true, message: "璇烽�夋嫨浜у搧", trigger: "blur" }],
+ version: [{ required: true, message: "璇疯緭鍏ョ増鏈彿", trigger: "blur" }],
+ };
+
+ const showProductPicker = ref(false);
+ const productQuery = reactive({
+ productName: "",
+ model: "",
+ });
+ const productList = ref([]);
+ const productPage = reactive({
+ current: 1,
+ size: 20,
+ total: 0,
+ });
+ const productPageStatus = ref("loadmore");
const goBack = () => {
uni.navigateBack();
@@ -144,6 +286,153 @@
});
};
+ const openAdd = () => {
+ formMode.value = "add";
+ Object.assign(bomForm, {
+ id: undefined,
+ productName: "",
+ productModelName: "",
+ productModelId: "",
+ remark: "",
+ version: "",
+ });
+ showFormPopup.value = true;
+ };
+
+ const openEdit = row => {
+ formMode.value = "edit";
+ Object.assign(bomForm, {
+ id: row.id,
+ productName: row.productName || "",
+ productModelName: row.productModelName || "",
+ productModelId: row.productModelId || "",
+ remark: row.remark || "",
+ version: row.version || "",
+ });
+ showFormPopup.value = true;
+ };
+
+ const closeFormPopup = () => {
+ showFormPopup.value = false;
+ };
+
+ const submitForm = () => {
+ if (!bomFormRef.value) return;
+ bomFormRef.value.validate(valid => {
+ if (!valid) return;
+ const payload = { ...bomForm };
+ const req = formMode.value === "add" ? add(payload) : update(payload);
+ req
+ .then(res => {
+ if (res && res.code !== undefined && res.code !== 200) {
+ uni.showToast({
+ title: res.msg || "鎻愪氦澶辫触",
+ icon: "none",
+ });
+ return;
+ }
+ uni.showToast({
+ title: "鎻愪氦鎴愬姛",
+ icon: "success",
+ });
+ closeFormPopup();
+ handleSearch();
+ })
+ .catch(() => {
+ uni.showToast({
+ title: "鎻愪氦澶辫触",
+ icon: "error",
+ });
+ });
+ });
+ };
+
+ const handleDelete = row => {
+ if (!row?.id) return;
+ uni.showModal({
+ title: "鎻愮ず",
+ content: "纭鍒犻櫎璇OM锛�",
+ confirmText: "纭",
+ cancelText: "鍙栨秷",
+ success: res => {
+ if (!res.confirm) return;
+ batchDelete([row.id])
+ .then(result => {
+ if (result && result.code !== undefined && result.code !== 200) {
+ uni.showToast({
+ title: result.msg || "鍒犻櫎澶辫触",
+ icon: "none",
+ });
+ return;
+ }
+ uni.showToast({
+ title: "鍒犻櫎鎴愬姛",
+ icon: "success",
+ });
+ handleSearch();
+ })
+ .catch(() => {
+ uni.showToast({
+ title: "鍒犻櫎澶辫触",
+ icon: "error",
+ });
+ });
+ },
+ });
+ };
+
+ const openProductPicker = () => {
+ showProductPicker.value = true;
+ handleProductSearch();
+ };
+
+ const handleProductSearch = () => {
+ productPage.current = 1;
+ productPageStatus.value = "loadmore";
+ productList.value = [];
+ loadMoreProducts();
+ };
+
+ const loadMoreProducts = () => {
+ if (
+ productPageStatus.value === "loading" ||
+ productPageStatus.value === "nomore"
+ ) {
+ return;
+ }
+ productPageStatus.value = "loading";
+ getProductList({
+ current: productPage.current,
+ size: productPage.size,
+ productName: productQuery.productName,
+ model: productQuery.model,
+ })
+ .then(res => {
+ const records = res?.data?.records || res?.records || res?.data || [];
+ const total = res?.data?.total || res?.total || 0;
+ const next = Array.isArray(records) ? records : [];
+ productList.value =
+ productPage.current === 1 ? next : [...productList.value, ...next];
+ productPage.total = Number(total || productList.value.length);
+ if (productList.value.length >= productPage.total) {
+ productPageStatus.value = "nomore";
+ } else {
+ productPageStatus.value = "loadmore";
+ productPage.current++;
+ }
+ })
+ .catch(() => {
+ productPageStatus.value = "loadmore";
+ });
+ };
+
+ const selectProduct = row => {
+ bomForm.productModelId = row.id;
+ bomForm.productName = row.productName || "";
+ bomForm.productModelName = row.model || "";
+ showProductPicker.value = false;
+ };
+
onReachBottom(() => {
getList();
});
@@ -176,4 +465,78 @@
margin: 0 !important;
margin-bottom: 15rpx !important;
}
+
+ .popup-container {
+ background: #fff;
+ border-radius: 20rpx 20rpx 0 0;
+ max-height: 80vh;
+ display: flex;
+ flex-direction: column;
+ }
+
+ .popup-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 24rpx 28rpx;
+ border-bottom: 1rpx solid #f0f0f0;
+ }
+
+ .popup-title {
+ font-size: 30rpx;
+ font-weight: 600;
+ color: #333;
+ }
+
+ .popup-cancel {
+ font-size: 28rpx;
+ color: #666;
+ }
+
+ .popup-confirm {
+ font-size: 28rpx;
+ color: #006cfb;
+ font-weight: 600;
+ }
+
+ .popup-body {
+ padding: 20rpx 24rpx 30rpx;
+ overflow: hidden;
+ flex: 1;
+ }
+
+ .picker-search {
+ display: flex;
+ gap: 16rpx;
+ margin-bottom: 16rpx;
+ }
+
+ .picker-list {
+ height: 60vh;
+ }
+
+ .picker-item {
+ padding: 22rpx 0;
+ border-bottom: 1rpx solid #f5f5f5;
+ }
+
+ .picker-item__title {
+ font-size: 28rpx;
+ color: #333;
+ font-weight: 600;
+ }
+
+ .picker-item__sub {
+ margin-top: 6rpx;
+ font-size: 24rpx;
+ color: #666;
+ display: flex;
+ justify-content: space-between;
+ gap: 16rpx;
+ }
+
+ .picker-item__unit {
+ color: #999;
+ white-space: nowrap;
+ }
</style>
--
Gitblit v1.9.3