| | |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view class="approval-process"> |
| | | <view class="approval-header"> |
| | | <text class="approval-title">审核流程</text> |
| | | <text class="approval-desc">每个步骤只能选择一个审批人</text> |
| | | </view> |
| | | <view class="approval-steps"> |
| | | <view v-for="(step, stepIndex) in stockApproverNodes" |
| | | :key="step.id" |
| | | class="approval-step"> |
| | | <view class="step-title"> |
| | | <text>审批人</text> |
| | | </view> |
| | | <view class="approver-container"> |
| | | <view v-if="step.userName" |
| | | class="approver-item"> |
| | | <view class="approver-avatar"> |
| | | <text class="avatar-text">{{ step.userName.charAt(0) }}</text> |
| | | </view> |
| | | <view class="approver-info"> |
| | | <text class="approver-name">{{ step.userName }}</text> |
| | | </view> |
| | | <view class="delete-approver-btn" |
| | | @click="removeApprover(stepIndex)">×</view> |
| | | </view> |
| | | <view v-else |
| | | class="add-approver-btn" |
| | | @click="openApproverPicker(stepIndex)"> |
| | | <view class="add-circle">+</view> |
| | | <text class="add-label">选择审批人</text> |
| | | </view> |
| | | </view> |
| | | <view class="delete-step-btn" |
| | | v-if="stockApproverNodes.length > 1" |
| | | @click="removeStockApproverNode(stepIndex)">删除节点</view> |
| | | </view> |
| | | </view> |
| | | <view class="add-step-btn"> |
| | | <u-button icon="plus" |
| | | plain |
| | | type="primary" |
| | | style="width: 100%" |
| | | @click="addStockApproverNode">新增节点</u-button> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="footer-btns"> |
| | | <u-button class="footer-cancel-btn" |
| | | @click="cancelForm">返回</u-button> |
| | |
| | | @click="confirmInbound">确认入库</u-button> |
| | | </view> |
| | | </scroll-view> |
| | | |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, computed } from "vue"; |
| | | import { ref, computed, onMounted, onUnmounted } from "vue"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import { productList as salesProductList } from "@/api/salesManagement/salesLedger"; |
| | | import modal from "@/plugins/modal"; |
| | |
| | | const contractKind = ref(CONTRACT_KIND.sales); |
| | | const scanLedgerId = ref(null); |
| | | const submitLoading = ref(false); |
| | | const stockApproverNodes = ref([{ id: 1, userId: null, userName: "" }]); |
| | | let nextApproverNodeId = 2; |
| | | const submitConfigByScene = createSubmitConfig(scanLedgerId); |
| | | |
| | | const cardTitleMain = computed(() => { |
| | |
| | | scanLedgerId.value = null; |
| | | expandedByIndex.value = {}; |
| | | recordList.value = []; |
| | | stockApproverNodes.value = [{ id: 1, userId: null, userName: "" }]; |
| | | }; |
| | | |
| | | const confirmInbound = async () => { |
| | | onMounted(() => { |
| | | uni.$on("selectContact", handleSelectContact); |
| | | }); |
| | | |
| | | onUnmounted(() => { |
| | | uni.$off("selectContact", handleSelectContact); |
| | | }); |
| | | |
| | | const addStockApproverNode = () => { |
| | | stockApproverNodes.value.push({ |
| | | id: nextApproverNodeId++, |
| | | userId: null, |
| | | userName: "", |
| | | }); |
| | | }; |
| | | |
| | | const removeStockApproverNode = index => { |
| | | if (stockApproverNodes.value.length <= 1) { |
| | | modal.msgError("至少保留一个审批节点"); |
| | | return; |
| | | } |
| | | stockApproverNodes.value.splice(index, 1); |
| | | }; |
| | | |
| | | const removeApprover = stepIndex => { |
| | | if (!stockApproverNodes.value[stepIndex]) return; |
| | | stockApproverNodes.value[stepIndex].userId = null; |
| | | stockApproverNodes.value[stepIndex].userName = ""; |
| | | }; |
| | | |
| | | const openApproverPicker = index => { |
| | | uni.setStorageSync("stepIndex", index); |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/collaborativeApproval/contactSelect?approveType=9", |
| | | }); |
| | | }; |
| | | |
| | | const handleSelectContact = data => { |
| | | const { stepIndex, contact } = data || {}; |
| | | if (stepIndex === null || stepIndex === undefined) return; |
| | | const idx = Number(stepIndex); |
| | | if (Number.isNaN(idx) || !stockApproverNodes.value[idx]) return; |
| | | stockApproverNodes.value[idx].userId = contact?.userId ?? null; |
| | | stockApproverNodes.value[idx].userName = contact?.nickName || contact?.userName || ""; |
| | | }; |
| | | |
| | | const validateApproverNodes = () => { |
| | | const hasEmptyNode = stockApproverNodes.value.some(node => !node.userId); |
| | | if (hasEmptyNode) { |
| | | modal.msgError("请为每个审批节点选择审批人"); |
| | | return false; |
| | | } |
| | | return true; |
| | | }; |
| | | |
| | | const submitInbound = async () => { |
| | | if (scanLedgerId.value == null || scanLedgerId.value === "") { |
| | | modal.msgError("缺少订单信息,请重新扫码"); |
| | | return; |
| | |
| | | return; |
| | | } |
| | | const runApi = currentSubmitConfig.runApi; |
| | | const payload = currentSubmitConfig.payloadBuilder(salesLedgerProductList); |
| | | const approveUserIds = stockApproverNodes.value.map(node => node.userId).join(","); |
| | | const payload = currentSubmitConfig.payloadBuilder(salesLedgerProductList, approveUserIds); |
| | | try { |
| | | submitLoading.value = true; |
| | | modal.loading("提交中..."); |
| | |
| | | } finally { |
| | | submitLoading.value = false; |
| | | } |
| | | }; |
| | | |
| | | const confirmInbound = () => { |
| | | if (!validateApproverNodes()) return; |
| | | submitInbound(); |
| | | }; |
| | | |
| | | const goBack = () => { |
| | |
| | | color: #fff; |
| | | border: none; |
| | | } |
| | | |
| | | .approval-process { |
| | | background: #fff; |
| | | margin: 20rpx; |
| | | border-radius: 16rpx; |
| | | padding: 24rpx; |
| | | } |
| | | |
| | | .approval-header { |
| | | margin-bottom: 16rpx; |
| | | } |
| | | |
| | | .approval-title { |
| | | font-size: 30rpx; |
| | | font-weight: 600; |
| | | color: #333; |
| | | display: block; |
| | | } |
| | | |
| | | .approval-desc { |
| | | font-size: 24rpx; |
| | | color: #999; |
| | | margin-top: 6rpx; |
| | | } |
| | | |
| | | .approval-step { |
| | | margin-bottom: 18rpx; |
| | | } |
| | | |
| | | .step-title text { |
| | | font-size: 24rpx; |
| | | color: #666; |
| | | } |
| | | |
| | | .approver-container { |
| | | display: flex; |
| | | align-items: center; |
| | | margin-top: 10rpx; |
| | | } |
| | | |
| | | .approver-item { |
| | | width: 100%; |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 12rpx; |
| | | padding: 12rpx 0; |
| | | } |
| | | |
| | | .approver-avatar { |
| | | width: 64rpx; |
| | | height: 64rpx; |
| | | border-radius: 50%; |
| | | background: #f3f4f6; |
| | | border: 2rpx solid #e5e7eb; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .avatar-text { |
| | | font-size: 24rpx; |
| | | color: #374151; |
| | | font-weight: 600; |
| | | } |
| | | |
| | | .approver-info { |
| | | flex: 1; |
| | | } |
| | | |
| | | .approver-name { |
| | | font-size: 28rpx; |
| | | color: #333; |
| | | } |
| | | |
| | | .delete-approver-btn { |
| | | font-size: 32rpx; |
| | | color: #ff4d4f; |
| | | padding: 0 8rpx; |
| | | } |
| | | |
| | | .add-approver-btn { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 10rpx; |
| | | color: #3b82f6; |
| | | padding: 10rpx 0; |
| | | } |
| | | |
| | | .add-circle { |
| | | width: 52rpx; |
| | | height: 52rpx; |
| | | border: 2rpx dashed #a0aec0; |
| | | border-radius: 50%; |
| | | color: #6b7280; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | font-size: 34rpx; |
| | | line-height: 1; |
| | | } |
| | | |
| | | .add-label { |
| | | font-size: 26rpx; |
| | | } |
| | | |
| | | .delete-step-btn { |
| | | color: #ff4d4f; |
| | | font-size: 24rpx; |
| | | margin-top: 8rpx; |
| | | } |
| | | |
| | | .add-step-btn { |
| | | margin-top: 8rpx; |
| | | } |
| | | </style> |