From 22229c67d87f0fae4c4bc90db106b8a1e2c49b53 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期四, 20 八月 2026 15:50:11 +0800
Subject: [PATCH] feat(permission): 为多个模块添加管理员权限控制功能
---
src/views/salesManagement/salesLedger/index.vue | 270 +++++++++++++++++++++++++++++++++++++++++------------
1 files changed, 206 insertions(+), 64 deletions(-)
diff --git a/src/views/salesManagement/salesLedger/index.vue b/src/views/salesManagement/salesLedger/index.vue
index 1e5a0fe..8d2a3d7 100644
--- a/src/views/salesManagement/salesLedger/index.vue
+++ b/src/views/salesManagement/salesLedger/index.vue
@@ -57,6 +57,10 @@
<el-button type="primary"
plain
@click="handlePrint">鎵撳嵃</el-button>
+ <el-button type="primary"
+ plain
+ :disabled="selectedRows.length === 0"
+ @click="handleBatchShipping">鎵归噺鍙戣揣</el-button>
</div>
</div>
<el-table :data="tableData"
@@ -647,7 +651,7 @@
:min="0"
v-model="productForm.taxInclusiveUnitPrice"
style="width: 100%"
- :precision="4"
+ :precision="5"
placeholder="璇疯緭鍏�"
clearable
@change="calculateFromQuantity" />
@@ -872,16 +876,15 @@
ref="deliveryFormRef">
<el-row :gutter="30">
<el-col :span="24">
- <el-form-item label="鍙戣揣绫诲瀷锛�"
- prop="type">
- <el-select v-model="deliveryForm.type"
- placeholder="璇烽�夋嫨鍙戣揣绫诲瀷"
- style="width: 100%">
- <el-option label="璐ц溅"
- value="璐ц溅" />
- <el-option label="蹇��"
- value="蹇��" />
- </el-select>
+ <el-form-item label="鏈鍙戣揣鏁伴噺锛�"
+ prop="quantity">
+ <el-input-number v-model="deliveryForm.quantity"
+ :min="0.01"
+ :max="Number(deliveryForm.unshippedQuantity)"
+ :precision="2"
+ placeholder="璇疯緭鍏ユ湰娆″彂璐ф暟閲�"
+ style="width: 100%" />
+ <span style="margin-left: 8px; color: #909399;">鍓╀綑鍙彂锛歿{ deliveryForm.unshippedQuantity }}</span>
</el-form-item>
</el-col>
</el-row>
@@ -894,14 +897,47 @@
</div>
</template>
</el-dialog>
+ <!-- 鎵归噺鍙戣揣寮规 -->
+ <el-dialog v-model="batchShippingOpen"
+ title="鎵归噺鍙戣揣"
+ width="60%"
+ @close="closeBatchShipping">
+ <el-table :data="batchShippingRows"
+ border>
+ <el-table-column label="浜у搧澶х被"
+ prop="productCategory" />
+ <el-table-column label="瑙勬牸鍨嬪彿"
+ prop="specificationModel" />
+ <el-table-column label="璁㈠崟鏁伴噺"
+ prop="quantity" />
+ <el-table-column label="鍓╀綑鍙彂"
+ prop="unshippedQuantity" />
+ <el-table-column label="鏈鍙戣揣鏁伴噺">
+ <template #default="scope">
+ <el-input-number v-model="scope.row.shipQuantity"
+ :min="0.01"
+ :max="Number(scope.row.unshippedQuantity)"
+ :precision="2"
+ size="small" />
+ </template>
+ </el-table-column>
+ </el-table>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button type="primary"
+ @click="submitBatchShipping">纭鍙戣揣</el-button>
+ <el-button @click="closeBatchShipping">鍙栨秷</el-button>
+ </div>
+ </template>
+ </el-dialog>
</div>
</template>
<script setup>
import { getToken } from "@/utils/auth";
import pagination from "@/components/PIMTable/Pagination.vue";
- import { onMounted, ref, getCurrentInstance } from "vue";
- import { addShippingInfo } from "@/api/salesManagement/deliveryLedger.js";
+ import { onMounted, ref, computed, getCurrentInstance } from "vue";
+ import { addShippingInfo, batchAdd } from "@/api/salesManagement/deliveryLedger.js";
import { ElMessageBox, ElMessage } from "element-plus";
import { UploadFilled, Download } from "@element-plus/icons-vue";
import useUserStore from "@/store/modules/user";
@@ -929,6 +965,9 @@
import { listCustomerPrivatePool } from "@/api/basicData/customerFile.js";
const userStore = useUserStore();
+ const isAdminUser = computed(() =>
+ ["admin", "鏅��2", "鏈�楂�1"].some(r => (userStore.roles || []).includes(r))
+ );
const { proxy } = getCurrentInstance();
const tableData = ref([]);
const productData = ref([]);
@@ -1052,13 +1091,23 @@
const currentDeliveryRow = ref(null);
const deliveryFormData = reactive({
deliveryForm: {
- type: "璐ц溅", // 璐ц溅, 蹇��
+ salesLedgerProductId: null,
+ salesLedgerId: null,
+ quantity: null, // 鏈鍙戣揣鏁伴噺
+ unshippedQuantity: 0, // 鍓╀綑鍙彂鏁伴噺锛堟墦寮�寮圭獥鏃惰祴鍊硷級
+ type: "閮ㄥ垎鍙戣揣",
+ approveUserIds: [],
+ tempFileIds: [],
},
deliveryRules: {
- type: [{ required: true, message: "璇烽�夋嫨鍙戣揣绫诲瀷", trigger: "change" }],
+ quantity: [{ required: true, message: "璇疯緭鍏ユ湰娆″彂璐ф暟閲�", trigger: "blur" }],
},
});
const { deliveryForm, deliveryRules } = toRefs(deliveryFormData);
+
+ // 鎵归噺鍙戣揣鐩稿叧
+ const batchShippingOpen = ref(false);
+ const batchShippingRows = ref([]);
// 瀵煎叆鐩稿叧
const importUploadRef = ref(null);
@@ -1179,6 +1228,12 @@
if (Number.isNaN(num)) return "0.0000";
return num.toFixed(4);
};
+ const formatAmount5 = value => {
+ if (value === undefined || value === null || value === "") return "0.00000";
+ const num = Number(value);
+ if (Number.isNaN(num)) return "0.00000";
+ return num.toFixed(5);
+ };
const findLedgerRecordByRow = row => {
if (!row) return null;
if (
@@ -1224,16 +1279,16 @@
}
return true;
};
- const canEditLedger = row => isCurrentUserMaintainer(row);
- const canDeleteLedger = row => isCurrentUserMaintainer(row);
+ const canEditLedger = row => isCurrentUserMaintainer(row) || isAdminUser.value;
+ const canDeleteLedger = row => isCurrentUserMaintainer(row) || isAdminUser.value;
const sensitiveAmountFormatter = (row, column, cellValue) => {
- if (!isCurrentUserMaintainer(row)) {
+ if (!isCurrentUserMaintainer(row) && !isAdminUser.value) {
return "*****";
}
return formattedNumber(row, column, cellValue);
};
const sensitiveAmountFormatter4 = (row, column, cellValue) => {
- if (!isCurrentUserMaintainer(row)) {
+ if (!isCurrentUserMaintainer(row) && !isAdminUser.value) {
return "*****";
}
return formattedAmount4(row, column, cellValue);
@@ -1356,7 +1411,7 @@
};
// 瀛愯〃鍚堣鏂规硶
const summarizeChildrenTable = (param, parentRow) => {
- if (!isCurrentUserMaintainer(parentRow)) {
+ if (!isCurrentUserMaintainer(parentRow) && !isAdminUser.value) {
const { columns } = param;
return columns.map((column, index) => {
if (index === 0) {
@@ -1663,7 +1718,7 @@
productForm.value.taxInclusiveUnitPrice !== null &&
productForm.value.taxInclusiveUnitPrice !== ""
) {
- productForm.value.taxInclusiveUnitPrice = formatAmount4(
+ productForm.value.taxInclusiveUnitPrice = formatAmount5(
productForm.value.taxInclusiveUnitPrice
);
}
@@ -2298,7 +2353,7 @@
productForm.value.taxInclusiveTotalPrice = totalPrice.toFixed(4);
// 璁$畻鍚◣鍗曚环 = 鍚◣鎬讳环 / 鏁伴噺
- productForm.value.taxInclusiveUnitPrice = (totalPrice / quantity).toFixed(4);
+ productForm.value.taxInclusiveUnitPrice = (totalPrice / quantity).toFixed(5);
// 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
if (productForm.value.taxRate) {
@@ -2342,7 +2397,7 @@
// 璁$畻鍚◣鍗曚环 = 鍚◣鎬讳环 / 鏁伴噺
productForm.value.taxInclusiveUnitPrice = (
inclusiveTotalPrice / quantity
- ).toFixed(4);
+ ).toFixed(5);
isCalculating.value = false;
};
@@ -2510,20 +2565,23 @@
* @param row 琛屾暟鎹�
*/
const canShip = row => {
- if (!row || !row.hasStockInventory) {
+ if (!row) {
return false;
}
-
- // 鑾峰彇鍙戣揣鐘舵��
- const shippingStatus = row.shippingStatus;
// 濡傛灉宸插彂璐э紙鏈夊彂璐ф棩鏈熸垨杞︾墝鍙凤級锛屼笉鑳藉啀娆″彂璐�
if (row.shippingDate || row.shippingCarNumber) {
return false;
}
+ // 浠呴渶瀛樺湪鍓╀綑鍙彂鏁伴噺锛堜笉鍐嶈姹傛湁搴撳瓨璁板綍/宸插畬宸ワ級
+ const qty = Number(row.unshippedQuantity);
+ if (!qty || qty <= 0) {
+ return false;
+ }
+
// 鍙戣揣鐘舵�佸繀椤绘槸"寰呭彂璐�"鎴�"瀹℃牳鎷掔粷"
- const statusStr = shippingStatus ? String(shippingStatus).trim() : "";
+ const statusStr = row.shippingStatus ? String(row.shippingStatus).trim() : "";
return statusStr === "寰呭彂璐�" || statusStr === "瀹℃牳鎷掔粷";
};
@@ -2575,55 +2633,70 @@
// 妫�鏌ユ槸鍚﹀彲浠ュ彂璐�
if (!canShip(row)) {
proxy.$modal.msgWarning(
- "鍙湁鍦ㄤ骇鍝佹湁搴撳瓨鏁伴噺锛屽彂璐х姸鎬佹槸寰呭彂璐ф垨瀹℃牳鎷掔粷鐨勬椂鍊欐墠鍙互鍙戣揣"
+ "鍙湁瀛樺湪鍓╀綑鍙彂鏁伴噺涓斿彂璐х姸鎬佷负寰呭彂璐ф垨瀹℃牳鎷掔粷鐨勬椂鍊欐墠鍙互鍙戣揣"
);
return;
}
currentDeliveryRow.value = row;
deliveryForm.value = {
- type: "璐ц溅",
+ salesLedgerProductId: row.id,
+ salesLedgerId: row.salesLedgerId,
+ quantity: row.unshippedQuantity, // 榛樿鍙栧墿浣欏彲鍙戞暟閲�
+ unshippedQuantity: row.unshippedQuantity,
+ type: "閮ㄥ垎鍙戣揣",
+ approveUserIds: [],
+ tempFileIds: [],
};
deliveryFormVisible.value = true;
};
// 鎻愪氦鍙戣揣琛ㄥ崟
const submitDelivery = () => {
- proxy.$refs["deliveryFormRef"].validate(valid => {
- if (valid) {
- // 淇濆瓨褰撳墠灞曞紑鐨勮ID锛屼互渚垮彂璐у悗閲嶆柊鍔犺浇瀛愯〃鏍兼暟鎹�
- const currentExpandedKeys = [...expandedRowKeys.value];
- const salesLedgerId = currentDeliveryRow.value.salesLedgerId;
- addShippingInfo({
- salesLedgerId: salesLedgerId,
- salesLedgerProductId: currentDeliveryRow.value.id,
- type: deliveryForm.value.type,
- }).then(() => {
- proxy.$modal.msgSuccess("鍙戣揣鎴愬姛");
- closeDeliveryDia();
- // 鍒锋柊涓昏〃鏁版嵁
- getList().then(() => {
- // 濡傛灉涔嬪墠鏈夊睍寮�鐨勮锛岄噸鏂板姞杞借繖浜涜鐨勫瓙琛ㄦ牸鏁版嵁
- if (currentExpandedKeys.length > 0) {
- // 浣跨敤 Promise.all 骞惰鍔犺浇鎵�鏈夊睍寮�琛岀殑瀛愯〃鏍兼暟鎹�
- const loadPromises = currentExpandedKeys.map(ledgerId => {
- return productList({ salesLedgerId: ledgerId, type: 1 }).then(
- res => {
- const index = tableData.value.findIndex(
- item => item.id === ledgerId
- );
- if (index > -1) {
- tableData.value[index].children = res.data;
- }
+ const qty = Number(deliveryForm.value.quantity);
+ if (!qty || qty <= 0) {
+ proxy.$modal.msgError("鏈鍙戣揣鏁伴噺蹇呴』澶т簬 0");
+ return;
+ }
+ if (qty > Number(deliveryForm.value.unshippedQuantity)) {
+ proxy.$modal.msgError("鏈鍙戣揣鏁伴噺涓嶈兘瓒呰繃鍓╀綑鍙彂鏁伴噺");
+ return;
+ }
+ // 淇濆瓨褰撳墠灞曞紑鐨勮ID锛屼互渚垮彂璐у悗閲嶆柊鍔犺浇瀛愯〃鏍兼暟鎹�
+ const currentExpandedKeys = [...expandedRowKeys.value];
+ addShippingInfo({
+ salesLedgerId: deliveryForm.value.salesLedgerId,
+ salesLedgerProductId: deliveryForm.value.salesLedgerProductId,
+ quantity: qty,
+ type: deliveryForm.value.type,
+ approveUserIds: deliveryForm.value.approveUserIds,
+ tempFileIds: deliveryForm.value.tempFileIds,
+ }).then(res => {
+ if (res.code === 200) {
+ proxy.$modal.msgSuccess("鍙戣揣鎴愬姛锛屽凡鍙戣捣瀹℃壒");
+ closeDeliveryDia();
+ // 鍒锋柊涓昏〃鏁版嵁
+ getList().then(() => {
+ // 濡傛灉涔嬪墠鏈夊睍寮�鐨勮锛岄噸鏂板姞杞借繖浜涜鐨勫瓙琛ㄦ牸鏁版嵁
+ if (currentExpandedKeys.length > 0) {
+ // 浣跨敤 Promise.all 骞惰鍔犺浇鎵�鏈夊睍寮�琛岀殑瀛愯〃鏍兼暟鎹�
+ const loadPromises = currentExpandedKeys.map(ledgerId => {
+ return productList({ salesLedgerId: ledgerId, type: 1 }).then(
+ res => {
+ const index = tableData.value.findIndex(
+ item => item.id === ledgerId
+ );
+ if (index > -1) {
+ tableData.value[index].children = res.data;
}
- );
- });
- Promise.all(loadPromises).then(() => {
- // 鎭㈠灞曞紑鐘舵��
- expandedRowKeys.value = currentExpandedKeys;
- });
- }
- });
+ }
+ );
+ });
+ Promise.all(loadPromises).then(() => {
+ // 鎭㈠灞曞紑鐘舵��
+ expandedRowKeys.value = currentExpandedKeys;
+ });
+ }
});
}
});
@@ -2635,6 +2708,75 @@
deliveryFormVisible.value = false;
currentDeliveryRow.value = null;
};
+
+ // 鎵归噺鍙戣揣锛氭牎楠屽悓涓�瀹㈡埛鍚庢媺鍙栧彲鍙戜骇鍝佽
+ const handleBatchShipping = async () => {
+ if (!selectedRows.value.length) {
+ proxy.$modal.msgWarning("璇峰厛鍕鹃�夎鍙戣揣鐨勮鍗�");
+ return;
+ }
+ // 鍚屼竴瀹㈡埛鏍¢獙锛堝悗绔篃浼氭牎楠岋級
+ const customerNames = [
+ ...new Set(selectedRows.value.map(l => l.customerName)),
+ ];
+ if (customerNames.length > 1) {
+ proxy.$modal.msgError("鎵归噺鍙戣揣浠呮敮鎸佸悓涓�瀹㈡埛鐨勫鏉¤鍗�");
+ return;
+ }
+ // 鎷夊彇鍚勮鍗曠殑浜у搧鏄庣粏锛屾敹闆嗗墿浣欏彲鍙戞暟閲� > 0 鐨勮
+ batchShippingRows.value = [];
+ for (const ledger of selectedRows.value) {
+ const res = await productList({ salesLedgerId: ledger.id, type: 1 });
+ const rows = (res.data || []).filter(r => Number(r.unshippedQuantity) > 0);
+ rows.forEach(r => {
+ r.salesLedgerId = ledger.id;
+ r.shipQuantity = r.unshippedQuantity; // 榛樿鏈鍙戣揣鏁伴噺 = 鍓╀綑鍙彂
+ });
+ batchShippingRows.value = batchShippingRows.value.concat(rows);
+ }
+ if (!batchShippingRows.value.length) {
+ proxy.$modal.msgWarning("鎵�閫夎鍗曟棤鍓╀綑鍙彂璐т骇鍝�");
+ return;
+ }
+ batchShippingOpen.value = true;
+ };
+
+ // 鎵归噺鎻愪氦鍙戣揣
+ const submitBatchShipping = () => {
+ // 閫愯鏍¢獙鏁伴噺
+ for (const row of batchShippingRows.value) {
+ const qty = Number(row.shipQuantity);
+ if (!qty || qty <= 0) {
+ proxy.$modal.msgError("瀛樺湪鏈鍙戣揣鏁伴噺涓虹┖鎴栦负 0 鐨勮");
+ return;
+ }
+ if (qty > Number(row.unshippedQuantity)) {
+ proxy.$modal.msgError("瀛樺湪瓒呰繃鍓╀綑鍙彂鏁伴噺鐨勮");
+ return;
+ }
+ }
+ const reqs = batchShippingRows.value.map(r => ({
+ salesLedgerId: r.salesLedgerId,
+ salesLedgerProductId: r.id,
+ quantity: r.shipQuantity,
+ type: "鎵归噺鍙戣揣",
+ approveUserIds: [],
+ }));
+ batchAdd(reqs).then(res => {
+ if (res.code === 200) {
+ proxy.$modal.msgSuccess("鎵归噺鍙戣揣鎴愬姛锛屽凡鍙戣捣瀹℃壒");
+ batchShippingOpen.value = false;
+ getList();
+ }
+ });
+ };
+
+ // 鍏抽棴鎵归噺鍙戣揣寮规
+ const closeBatchShipping = () => {
+ batchShippingOpen.value = false;
+ batchShippingRows.value = [];
+ };
+
const currentFactoryName = ref("");
const getCurrentFactoryName = async () => {
let res = await userStore.getInfo();
--
Gitblit v1.9.3