| | |
| | | |
| | | <view class="module-info"> |
| | | |
| | | <text class="module-label">合格发货</text> |
| | | <text class="module-label">合格出库</text> |
| | | |
| | | <text class="module-desc">扫描销售订单,填写发货数量、车牌与审批人后提交发货审批(通过后自动发货)</text> |
| | | <text class="module-desc">记录合格品的出库流向,销售二维码扫描发货</text> |
| | | |
| | | </view> |
| | | |
| | |
| | | |
| | | <view class="scan-ship-title">发货信息</view> |
| | | |
| | | <u-form label-width="160rpx"> |
| | | <u-form label-width="220rpx"> |
| | | |
| | | <u-form-item label="发货方式" |
| | | |
| | | class="scan-ship-type-form-item" |
| | | |
| | | required> |
| | | |
| | | <u-input v-model="scanShipTypeLabel" |
| | | <view class="scan-ship-type-trigger" |
| | | |
| | | readonly |
| | | @tap.stop="openScanShipTypeSheet"> |
| | | |
| | | placeholder="请选择" |
| | | <u-input v-model="scanShipTypeLabel" |
| | | |
| | | @click="scanShipTypeSheetShow = true" /> |
| | | readonly |
| | | |
| | | placeholder="请选择" /> |
| | | |
| | | <u-icon name="arrow-right" |
| | | |
| | | color="#c0c4cc" |
| | | |
| | | size="18" /> |
| | | |
| | | </view> |
| | | |
| | | </u-form-item> |
| | | |
| | |
| | | |
| | | </u-form> |
| | | |
| | | <view class="scan-ship-approval"> |
| | | <view class="approval-process"> |
| | | |
| | | <text class="scan-ship-subtitle">审批人</text> |
| | | <view class="approval-header"> |
| | | |
| | | <view v-if="scanShipApprover.nickName" |
| | | <text class="approval-title">审批流程</text> |
| | | |
| | | class="scan-ship-approver-pill"> |
| | | |
| | | <text>{{ scanShipApprover.nickName }}</text> |
| | | |
| | | <text class="scan-ship-remove" |
| | | |
| | | @click="clearScanShipApprover">×</text> |
| | | <text class="approval-desc">每个步骤只能选择一个审批人</text> |
| | | |
| | | </view> |
| | | |
| | | <u-button v-else |
| | | <view class="approval-steps"> |
| | | |
| | | size="small" |
| | | <view v-for="(step, stepIndex) in scanShipApproverNodes" |
| | | |
| | | type="primary" |
| | | :key="step.id" |
| | | |
| | | plain |
| | | class="approval-step"> |
| | | |
| | | @click="openScanShipContactSelect">选择审批人</u-button> |
| | | <view class="step-title"> |
| | | |
| | | <text>审批人</text> |
| | | |
| | | </view> |
| | | |
| | | <view class="approver-container"> |
| | | |
| | | <view v-if="step.nickName" |
| | | |
| | | class="approver-item"> |
| | | |
| | | <view class="approver-avatar"> |
| | | |
| | | <text class="avatar-text">{{ step.nickName.charAt(0) }}</text> |
| | | |
| | | </view> |
| | | |
| | | <view class="approver-info"> |
| | | |
| | | <text class="approver-name">{{ step.nickName }}</text> |
| | | |
| | | </view> |
| | | |
| | | <view class="delete-approver-btn" |
| | | |
| | | @tap.stop="removeScanShipApproverUser(stepIndex)">×</view> |
| | | |
| | | </view> |
| | | |
| | | <view v-else |
| | | |
| | | class="add-approver-btn" |
| | | |
| | | @tap.stop="openScanShipContactSelect(stepIndex)"> |
| | | |
| | | <view class="add-circle">+</view> |
| | | |
| | | <text class="add-label">选择审批人</text> |
| | | |
| | | </view> |
| | | |
| | | </view> |
| | | |
| | | <view class="delete-step-btn" |
| | | |
| | | v-if="scanShipApproverNodes.length > 1" |
| | | |
| | | @tap.stop="removeScanShipApproverNode(stepIndex)">删除节点</view> |
| | | |
| | | </view> |
| | | |
| | | </view> |
| | | |
| | | <view class="add-step-btn"> |
| | | |
| | | <u-button icon="plus" |
| | | |
| | | plain |
| | | |
| | | type="primary" |
| | | |
| | | style="width: 100%" |
| | | |
| | | @click="addScanShipApproverNode">新增节点</u-button> |
| | | |
| | | </view> |
| | | |
| | | </view> |
| | | |
| | |
| | | |
| | | <text class="scan-ship-subtitle">发货附件(选填,最多10张)</text> |
| | | |
| | | <u-button size="small" |
| | | <u-button class="scan-ship-add-img-btn" |
| | | |
| | | size="small" |
| | | |
| | | type="primary" |
| | | |
| | |
| | | ]); |
| | | const scanShipCarNumber = ref(""); |
| | | const scanShipExpress = ref(""); |
| | | const scanShipApprover = ref({ userId: null, nickName: null }); |
| | | let nextScanShipApproverNodeId = 2; |
| | | const scanShipApproverNodes = ref([{ id: 1, userId: null, nickName: "" }]); |
| | | const scanShipFiles = ref([]); |
| | | const scanShipUploading = ref(false); |
| | | |
| | |
| | | else scanShipCarNumber.value = ""; |
| | | }; |
| | | |
| | | const openScanShipContactSelect = () => { |
| | | uni.setStorageSync("stepIndex", 0); |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/collaborativeApproval/contactSelect?approveType=7&source=scanShip", |
| | | const openScanShipTypeSheet = () => { |
| | | scanShipTypeSheetShow.value = true; |
| | | }; |
| | | |
| | | const addScanShipApproverNode = () => { |
| | | scanShipApproverNodes.value.push({ |
| | | id: nextScanShipApproverNodeId++, |
| | | userId: null, |
| | | nickName: "", |
| | | }); |
| | | }; |
| | | |
| | | const clearScanShipApprover = () => { |
| | | scanShipApprover.value = { userId: null, nickName: null }; |
| | | const removeScanShipApproverNode = stepIndex => { |
| | | if (scanShipApproverNodes.value.length <= 1) return; |
| | | scanShipApproverNodes.value.splice(stepIndex, 1); |
| | | }; |
| | | |
| | | const removeScanShipApproverUser = stepIndex => { |
| | | const step = scanShipApproverNodes.value[stepIndex]; |
| | | if (!step) return; |
| | | step.userId = null; |
| | | step.nickName = ""; |
| | | }; |
| | | |
| | | const openScanShipContactSelect = stepIndex => { |
| | | uni.setStorageSync("stepIndex", stepIndex); |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/collaborativeApproval/contactSelect?approveType=7&source=scanShip", |
| | | }); |
| | | }; |
| | | |
| | | const handleScanShipSelectContact = data => { |
| | |
| | | if (!needScanShipFlow.value) return; |
| | | const c = data?.contact; |
| | | if (!c) return; |
| | | scanShipApprover.value = { userId: c.userId, nickName: c.nickName }; |
| | | const idx = Number(data.stepIndex); |
| | | const i = Number.isNaN(idx) ? 0 : idx; |
| | | if (i < 0 || i >= scanShipApproverNodes.value.length) return; |
| | | const row = scanShipApproverNodes.value[i]; |
| | | row.userId = c.userId; |
| | | row.nickName = c.nickName || c.userName || ""; |
| | | }; |
| | | |
| | | const scanShipFileUrl = file => { |
| | |
| | | modal.msgError("请输入快递单号"); |
| | | return; |
| | | } |
| | | if (!scanShipApprover.value?.userId) { |
| | | modal.msgError("请选择审批人"); |
| | | const hasEmptyStep = scanShipApproverNodes.value.some(s => !s?.userId); |
| | | if (hasEmptyStep) { |
| | | modal.msgError("请为每个审批步骤选择审批人"); |
| | | return; |
| | | } |
| | | if (scanShipUploading.value) { |
| | | modal.msgError("附件上传中,请稍候"); |
| | | return; |
| | | } |
| | | const approveUserIds = scanShipApproverNodes.value |
| | | .map(s => s.userId) |
| | | .filter(id => id != null && id !== "") |
| | | .join(","); |
| | | const payload = { |
| | | salesLedgerId: scanLedgerId.value, |
| | | salesLedgerProductList, |
| | | approveUserIds: String(scanShipApprover.value.userId), |
| | | approveUserIds, |
| | | shipType: scanShipTypeValue.value, |
| | | shippingCarNumber: |
| | | scanShipTypeValue.value === "货车" ? String(scanShipCarNumber.value || "").trim() : "", |
| | |
| | | scanShipTypeValue.value = "货车"; |
| | | scanShipCarNumber.value = ""; |
| | | scanShipExpress.value = ""; |
| | | scanShipApprover.value = { userId: null, nickName: null }; |
| | | nextScanShipApproverNodeId = 2; |
| | | scanShipApproverNodes.value = [{ id: 1, userId: null, nickName: "" }]; |
| | | scanShipFiles.value = []; |
| | | scanShipUploading.value = false; |
| | | scanShipTypeSheetShow.value = false; |
| | |
| | | |
| | | height: 140rpx; |
| | | |
| | | min-width: 140rpx; |
| | | |
| | | min-height: 140rpx; |
| | | |
| | | flex-shrink: 0; |
| | | |
| | | border-radius: 32rpx; |
| | | |
| | | display: flex; |
| | |
| | | display: flex; |
| | | |
| | | flex-direction: column; |
| | | |
| | | flex: 1; |
| | | |
| | | min-width: 0; |
| | | |
| | | } |
| | | |
| | |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | /* 发货信息:与扫码入库审批区、台账发货页表单风格一致 */ |
| | | |
| | | .scan-ship-card { |
| | | |
| | | background-color: #fff; |
| | | |
| | | margin: 20rpx; |
| | | |
| | | padding: 0 0 24rpx; |
| | | |
| | | border-radius: 16rpx; |
| | | |
| | | box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06); |
| | | |
| | | overflow: hidden; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-title { |
| | | |
| | | font-size: 30rpx; |
| | | |
| | | font-weight: 600; |
| | | |
| | | color: #333; |
| | | |
| | | padding: 28rpx 28rpx 20rpx; |
| | | |
| | | border-bottom: 1rpx solid #eee; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-card :deep(.u-form) { |
| | | |
| | | background: transparent; |
| | | |
| | | margin: 0; |
| | | |
| | | padding: 0; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-card :deep(.u-form-item) { |
| | | |
| | | background: #fff; |
| | | |
| | | padding: 0 28rpx; |
| | | |
| | | border-bottom: 1rpx solid #f0f0f0; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-card :deep(.u-form-item:last-child) { |
| | | |
| | | border-bottom: none; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-card :deep(.u-form-item__body) { |
| | | |
| | | padding: 24rpx 0; |
| | | |
| | | min-height: 88rpx; |
| | | |
| | | display: flex; |
| | | |
| | | align-items: center; |
| | | |
| | | border: none; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-card :deep(.u-form-item__label) { |
| | | |
| | | font-size: 28rpx; |
| | | |
| | | color: #888; |
| | | |
| | | font-weight: 400; |
| | | |
| | | flex-shrink: 0; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-card :deep(.u-form-item__content) { |
| | | |
| | | flex: 1; |
| | | |
| | | min-width: 0; |
| | | |
| | | display: flex; |
| | | |
| | | justify-content: flex-end; |
| | | |
| | | align-items: center; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-card :deep(.u-input), |
| | | |
| | | .scan-ship-card :deep(.u-input input), |
| | | |
| | | .scan-ship-card :deep(.u-input__content__field-wrapper__field), |
| | | |
| | | .scan-ship-card :deep(.u-input__input) { |
| | | |
| | | border: none !important; |
| | | |
| | | box-shadow: none !important; |
| | | |
| | | background: transparent !important; |
| | | |
| | | font-size: 28rpx; |
| | | |
| | | color: #1a1a1a; |
| | | |
| | | text-align: right; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-card :deep(.u-input input[readonly]), |
| | | |
| | | .scan-ship-card :deep(.u-input__input[readonly]) { |
| | | |
| | | color: #666; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-card :deep(.scan-ship-type-form-item .u-form-item__content) { |
| | | |
| | | justify-content: flex-start; |
| | | |
| | | align-items: center; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-type-trigger { |
| | | |
| | | display: flex; |
| | | |
| | | flex-direction: row; |
| | | |
| | | align-items: center; |
| | | |
| | | width: 100%; |
| | | |
| | | min-height: 72rpx; |
| | | |
| | | padding: 8rpx 0; |
| | | |
| | | box-sizing: border-box; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-type-trigger :deep(.u-input) { |
| | | |
| | | flex: 1; |
| | | |
| | | min-width: 0; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-type-trigger :deep(input), |
| | | |
| | | .scan-ship-type-trigger :deep(.u-input__input) { |
| | | |
| | | pointer-events: none; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-card :deep(.u-input input::placeholder), |
| | | |
| | | .scan-ship-card :deep(.u-input__input::placeholder) { |
| | | |
| | | color: #c0c4cc; |
| | | |
| | | font-size: 28rpx; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-card :deep(.scan-ship-type-form-item .u-input input), |
| | | |
| | | .scan-ship-card :deep(.scan-ship-type-form-item .u-input__input) { |
| | | |
| | | text-align: left; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-card .approval-process { |
| | | |
| | | background: transparent; |
| | | |
| | | margin: 0; |
| | | |
| | | padding: 24rpx 28rpx 8rpx; |
| | | |
| | | border-radius: 0; |
| | | |
| | | box-shadow: none; |
| | | |
| | | border-top: 1rpx solid #f0f0f0; |
| | | |
| | | margin-top: 8rpx; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-card .approval-header { |
| | | |
| | | margin-bottom: 16rpx; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-card .approval-title { |
| | | |
| | | font-size: 30rpx; |
| | | |
| | | font-weight: 600; |
| | | |
| | | color: #333; |
| | | |
| | | display: block; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-card .approval-desc { |
| | | |
| | | font-size: 24rpx; |
| | | |
| | | color: #999; |
| | | |
| | | margin-top: 6rpx; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-card .approval-step { |
| | | |
| | | margin-bottom: 18rpx; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-card .step-title text { |
| | | |
| | | font-size: 24rpx; |
| | | |
| | | color: #666; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-card .approver-container { |
| | | |
| | | display: flex; |
| | | |
| | | align-items: center; |
| | | |
| | | margin-top: 10rpx; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-card .approver-item { |
| | | |
| | | width: 100%; |
| | | |
| | | display: flex; |
| | | |
| | | align-items: center; |
| | | |
| | | gap: 12rpx; |
| | | |
| | | padding: 12rpx 0; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-card .approver-avatar { |
| | | |
| | | width: 64rpx; |
| | | |
| | | height: 64rpx; |
| | | |
| | | border-radius: 50%; |
| | | |
| | | background: #f3f4f6; |
| | | |
| | | border: 2rpx solid #e5e7eb; |
| | | |
| | | display: flex; |
| | | |
| | | align-items: center; |
| | | |
| | | justify-content: center; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-card .avatar-text { |
| | | |
| | | font-size: 24rpx; |
| | | |
| | | color: #374151; |
| | | |
| | | font-weight: 600; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-card .approver-info { |
| | | |
| | | flex: 1; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-card .approver-name { |
| | | |
| | | font-size: 28rpx; |
| | | |
| | | color: #333; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-card .delete-approver-btn { |
| | | |
| | | font-size: 32rpx; |
| | | |
| | | color: #ff4d4f; |
| | | |
| | | padding: 0 8rpx; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-card .add-approver-btn { |
| | | |
| | | display: flex; |
| | | |
| | | align-items: center; |
| | | |
| | | gap: 10rpx; |
| | | |
| | | color: #3b82f6; |
| | | |
| | | padding: 10rpx 0; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-card .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; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-card .add-label { |
| | | |
| | | font-size: 26rpx; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-card .delete-step-btn { |
| | | |
| | | color: #ff4d4f; |
| | | |
| | | font-size: 24rpx; |
| | | |
| | | margin-top: 8rpx; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-card .add-step-btn { |
| | | |
| | | margin-top: 8rpx; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-subtitle { |
| | | |
| | | display: block; |
| | | |
| | | font-size: 24rpx; |
| | | |
| | | color: #666; |
| | | |
| | | margin-bottom: 16rpx; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-files { |
| | | |
| | | padding: 28rpx 28rpx 0; |
| | | |
| | | border-top: 1rpx solid #f0f0f0; |
| | | |
| | | margin-top: 16rpx; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-files :deep(.scan-ship-add-img-btn) { |
| | | |
| | | width: 100% !important; |
| | | |
| | | margin-top: 8rpx; |
| | | |
| | | border-radius: 16rpx !important; |
| | | |
| | | min-height: 88rpx; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-file-grid { |
| | | |
| | | display: flex; |
| | | |
| | | flex-wrap: wrap; |
| | | |
| | | gap: 24rpx; |
| | | |
| | | margin-top: 24rpx; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-thumb-wrap { |
| | | |
| | | position: relative; |
| | | |
| | | width: calc(50% - 12rpx); |
| | | |
| | | min-width: 200rpx; |
| | | |
| | | padding: 16rpx; |
| | | |
| | | box-sizing: border-box; |
| | | |
| | | background: #fff; |
| | | |
| | | border-radius: 16rpx; |
| | | |
| | | border: 1rpx solid #e9ecef; |
| | | |
| | | box-shadow: 0 4rpx 8rpx rgba(0, 0, 0, 0.05); |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-thumb { |
| | | |
| | | width: 100%; |
| | | |
| | | height: 200rpx; |
| | | |
| | | border-radius: 12rpx; |
| | | |
| | | display: block; |
| | | |
| | | border: 2rpx solid #f0f0f0; |
| | | |
| | | background: #f5f5f5; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-thumb-del { |
| | | |
| | | position: absolute; |
| | | |
| | | top: 8rpx; |
| | | |
| | | right: 8rpx; |
| | | |
| | | width: 44rpx; |
| | | |
| | | height: 44rpx; |
| | | |
| | | background: #ff4757; |
| | | |
| | | color: #fff; |
| | | |
| | | font-size: 28rpx; |
| | | |
| | | line-height: 44rpx; |
| | | |
| | | text-align: center; |
| | | |
| | | border-radius: 50%; |
| | | |
| | | box-shadow: 0 4rpx 8rpx rgba(255, 71, 87, 0.35); |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .scan-ship-qty-readonly { |
| | | |
| | | font-size: 30rpx; |