| | |
| | | <template> |
| | | <view class="account-detail"> |
| | | <PageHeader title="新增采购退货" @back="goBack" /> |
| | | <up-form ref="formRef" :model="form" :rules="rules" label-width="120"> |
| | | <u-cell-group title="基本信息" class="form-section"> |
| | | <up-form-item label="退料单号" prop="no"> |
| | | <up-input |
| | | v-model="form.no" |
| | | <PageHeader title="新增采购退货" |
| | | @back="goBack" /> |
| | | <up-form ref="formRef" |
| | | :model="form" |
| | | :rules="rules" |
| | | label-width="110"> |
| | | <up-form-item label="退料单号" |
| | | prop="no"> |
| | | <up-input v-model="form.no" |
| | | :disabled="form.isDefaultNo" |
| | | :placeholder="form.isDefaultNo ? '使用系统编号' : '请输入退料单号'" |
| | | clearable |
| | | /> |
| | | clearable /> |
| | | <template #right> |
| | | <up-switch v-model="form.isDefaultNo" @change="onDefaultNoChange" /> |
| | | <up-switch v-model="form.isDefaultNo" |
| | | @change="onDefaultNoChange" /> |
| | | </template> |
| | | </up-form-item> |
| | | <up-form-item label="退货方式" prop="returnType" required> |
| | | <up-input |
| | | v-model="returnTypeText" |
| | | <up-form-item label="退货方式" |
| | | prop="returnType" |
| | | required> |
| | | <up-input v-model="returnTypeText" |
| | | placeholder="请选择" |
| | | readonly |
| | | @click="showReturnTypeSheet = true" |
| | | /> |
| | | @click="showReturnTypeSheet = true" /> |
| | | <template #right> |
| | | <up-icon name="arrow-right" @click="showReturnTypeSheet = true"></up-icon> |
| | | <up-icon name="arrow-right" |
| | | @click="showReturnTypeSheet = true"></up-icon> |
| | | </template> |
| | | </up-form-item> |
| | | <up-form-item label="供应商" prop="supplierId" required> |
| | | <up-input |
| | | v-model="supplierText" |
| | | <up-form-item label="供应商" |
| | | prop="supplierName" |
| | | required> |
| | | <up-input v-model="form.supplierName" |
| | | placeholder="请选择" |
| | | readonly |
| | | @click="showSupplierSheet = true" |
| | | /> |
| | | @click="showSupplierSheet = true" /> |
| | | <template #right> |
| | | <up-icon name="arrow-right" @click="showSupplierSheet = true"></up-icon> |
| | | <up-icon name="arrow-right" |
| | | @click="showSupplierSheet = true"></up-icon> |
| | | </template> |
| | | </up-form-item> |
| | | <up-form-item label="项目阶段" prop="projectPhase"> |
| | | <up-input |
| | | v-model="projectPhaseText" |
| | | <up-form-item label="项目阶段" |
| | | prop="projectPhase"> |
| | | <up-input v-model="projectPhaseText" |
| | | placeholder="请选择" |
| | | readonly |
| | | @click="showProjectPhaseSheet = true" |
| | | /> |
| | | @click="showProjectPhaseSheet = true" /> |
| | | <template #right> |
| | | <up-icon name="arrow-right" @click="showProjectPhaseSheet = true"></up-icon> |
| | | <up-icon name="arrow-right" |
| | | @click="showProjectPhaseSheet = true"></up-icon> |
| | | </template> |
| | | </up-form-item> |
| | | <up-form-item label="制作日期" prop="preparedAt" required> |
| | | <up-input |
| | | v-model="form.preparedAt" |
| | | <up-form-item label="制作日期" |
| | | prop="preparedAt" |
| | | required> |
| | | <up-input v-model="form.preparedAt" |
| | | placeholder="请选择" |
| | | readonly |
| | | @click="showPreparedAtPicker = true" |
| | | /> |
| | | @click="showPreparedAtPicker = true" /> |
| | | <template #right> |
| | | <up-icon name="arrow-right" @click="showPreparedAtPicker = true"></up-icon> |
| | | <up-icon name="arrow-right" |
| | | @click="showPreparedAtPicker = true"></up-icon> |
| | | </template> |
| | | </up-form-item> |
| | | <up-form-item label="制单人" prop="preparedUserId" required> |
| | | <up-input |
| | | v-model="preparedUserText" |
| | | <up-form-item label="制单人" |
| | | prop="preparedUserName" |
| | | required> |
| | | <up-input v-model="form.preparedUserName" |
| | | placeholder="请选择" |
| | | readonly |
| | | @click="showPreparedUserSheet = true" |
| | | /> |
| | | @click="openPreparedUserSheet" /> |
| | | <template #right> |
| | | <up-icon name="arrow-right" @click="showPreparedUserSheet = true"></up-icon> |
| | | <up-icon name="arrow-right" |
| | | @click="openPreparedUserSheet"></up-icon> |
| | | </template> |
| | | </up-form-item> |
| | | <up-form-item label="退料人" prop="returnUserId" required> |
| | | <up-input |
| | | v-model="returnUserText" |
| | | <up-form-item label="退料人" |
| | | prop="returnUserName" |
| | | required> |
| | | <up-input v-model="form.returnUserName" |
| | | placeholder="请选择" |
| | | readonly |
| | | @click="showReturnUserSheet = true" |
| | | /> |
| | | @click="openReturnUserSheet" /> |
| | | <template #right> |
| | | <up-icon name="arrow-right" @click="showReturnUserSheet = true"></up-icon> |
| | | <up-icon name="arrow-right" |
| | | @click="openReturnUserSheet"></up-icon> |
| | | </template> |
| | | </up-form-item> |
| | | <up-form-item label="采购合同号" prop="purchaseLedgerId" required> |
| | | <up-input |
| | | v-model="purchaseContractText" |
| | | <up-form-item label="采购合同号" |
| | | prop="purchaseContractNumber" |
| | | required> |
| | | <up-input v-model="form.purchaseContractNumber" |
| | | placeholder="请选择" |
| | | readonly |
| | | @click="showPurchaseLedgerSheet = true" |
| | | /> |
| | | @click="showPurchaseLedgerSheet = true" /> |
| | | <template #right> |
| | | <up-icon name="arrow-right" @click="showPurchaseLedgerSheet = true"></up-icon> |
| | | <up-icon name="arrow-right" |
| | | @click="showPurchaseLedgerSheet = true"></up-icon> |
| | | </template> |
| | | </up-form-item> |
| | | <up-form-item label="备注" prop="remark"> |
| | | <up-textarea v-model="form.remark" placeholder="请输入" auto-height /> |
| | | <up-form-item label="备注" |
| | | prop="remark"> |
| | | <up-textarea v-model="form.remark" |
| | | placeholder="请输入备注" |
| | | auto-height /> |
| | | </up-form-item> |
| | | </u-cell-group> |
| | | |
| | | <u-cell-group title="产品列表" class="form-section"> |
| | | <view class="product-actions"> |
| | | <up-button |
| | | type="primary" |
| | | size="small" |
| | | text="选择产品" |
| | | :disabled="!form.purchaseLedgerId" |
| | | @click="goSelectProducts" |
| | | /> |
| | | <view class="amount-summary"> |
| | | <view class="product-section"> |
| | | <view class="section-header"> |
| | | <view> |
| | | <text class="section-title">产品信息</text> |
| | | </view> |
| | | <view class="section-actions"> |
| | | <text class="amount-text">合计:{{ formatAmount(baseAmount) }}</text> |
| | | <up-button type="primary" |
| | | size="small" |
| | | class="add-btn" |
| | | :disabled="!form.purchaseLedgerId" |
| | | @click="goSelectProducts"> |
| | | 选择产品 |
| | | </up-button> |
| | | </view> |
| | | </view> |
| | | <view v-if="form.purchaseReturnOrderProductsDtos.length === 0" class="empty-products"> |
| | | <view v-if="form.purchaseReturnOrderProductsDtos.length === 0" |
| | | class="empty-products"> |
| | | <text>暂无产品,请先选择产品</text> |
| | | </view> |
| | | <view v-else class="product-list"> |
| | | <view |
| | | <view v-else> |
| | | <view class="product-card" |
| | | v-for="(item, index) in form.purchaseReturnOrderProductsDtos" |
| | | :key="item.salesLedgerProductId || item.id || index" |
| | | class="product-card" |
| | | > |
| | | :key="item.id || index"> |
| | | <view class="product-header"> |
| | | <view class="product-title"> |
| | | <view class="document-icon"> |
| | | <up-icon name="file-text" size="16" color="#ffffff"></up-icon> |
| | | <up-icon name="file-text" |
| | | size="16" |
| | | color="#2979ff"></up-icon> |
| | | <text class="product-productCategory">产品 {{ index + 1 }}</text> |
| | | </view> |
| | | <text class="product-name">产品 {{ index + 1 }}</text> |
| | | <view> |
| | | <up-button type="error" |
| | | size="mini" |
| | | class="del-btn" |
| | | @click="removeProduct(index)"> |
| | | 删除 |
| | | </up-button> |
| | | </view> |
| | | <up-icon name="trash" size="18" color="#ee0a24" @click="removeProduct(index)" /> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | <view class="product-body"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">产品大类</text> |
| | | <text class="detail-value">{{ item.productCategory || "-" }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">规格型号</text> |
| | | <text class="detail-value">{{ item.specificationModel || "-" }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">数量</text> |
| | | <text class="detail-value">{{ item.quantity ?? "-" }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">含税单价(元)</text> |
| | | <text class="detail-value">{{ formatAmount(item.taxInclusiveUnitPrice) }}</text> |
| | | </view> |
| | | <view class="qty-row"> |
| | | <text class="qty-label">退货数量</text> |
| | | <up-number-box |
| | | v-model="item.returnQuantity" |
| | | <view class="product-form"> |
| | | <up-form-item label="产品大类"> |
| | | <up-input :modelValue="item.productCategory || '-'" |
| | | disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="规格型号"> |
| | | <up-input :modelValue="item.specificationModel || '-'" |
| | | disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="入库数量"> |
| | | <up-input :modelValue="String(item.stockInNum ?? item.quantity ?? '-')" |
| | | disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="可退货数量"> |
| | | <up-input :modelValue="String(item.unQuantity ?? '-')" |
| | | disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="含税单价(元)"> |
| | | <up-input :modelValue="formatAmount(item.taxInclusiveUnitPrice)" |
| | | disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="退货数量"> |
| | | <up-number-box v-model="item.returnQuantity" |
| | | :min="0" |
| | | :max="getReturnQtyMax(item)" |
| | | :step="1" |
| | | @change="syncRowTotal(item)" |
| | | /> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">退货总价(元)</text> |
| | | <text class="detail-value highlight">{{ formatAmount(item.taxInclusiveTotalPrice) }}</text> |
| | | @change="syncRowTotal(item)" /> |
| | | </up-form-item> |
| | | <up-form-item label="退货总价(元)"> |
| | | <up-input :modelValue="formatAmount(item.taxInclusiveTotalPrice)" |
| | | disabled /> |
| | | </up-form-item> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </u-cell-group> |
| | | |
| | | <u-cell-group title="费用信息" class="form-section"> |
| | | <up-form-item label="整单折扣额" prop="totalDiscountAmount"> |
| | | <up-input |
| | | v-model="form.totalDiscountAmount" |
| | | <up-form-item label="整单折扣额" |
| | | prop="totalDiscountAmount"> |
| | | <up-input v-model="form.totalDiscountAmount" |
| | | type="number" |
| | | placeholder="请输入" |
| | | @blur="onDiscountAmountBlur" |
| | | clearable |
| | | /> |
| | | clearable /> |
| | | </up-form-item> |
| | | <up-form-item label="整单折扣率(%)" prop="totalDiscountRate"> |
| | | <up-input |
| | | v-model="form.totalDiscountRate" |
| | | <up-form-item label="整单折扣率(%)" |
| | | prop="totalDiscountRate"> |
| | | <up-input v-model="form.totalDiscountRate" |
| | | type="number" |
| | | placeholder="请输入" |
| | | @blur="onDiscountRateBlur" |
| | | clearable |
| | | /> |
| | | clearable /> |
| | | </up-form-item> |
| | | <up-form-item label="成交金额" prop="totalAmount" required> |
| | | <up-input v-model="form.totalAmount" disabled placeholder="自动计算" /> |
| | | <up-form-item label="成交金额" |
| | | prop="totalAmount" |
| | | required> |
| | | <up-input v-model="form.totalAmount" |
| | | disabled |
| | | placeholder="自动计算" /> |
| | | </up-form-item> |
| | | <up-form-item label="收款方式" prop="incomeType" required> |
| | | <up-input |
| | | v-model="incomeTypeText" |
| | | <up-form-item label="收款方式" |
| | | prop="incomeType" |
| | | required> |
| | | <up-input v-model="incomeTypeText" |
| | | placeholder="请选择" |
| | | readonly |
| | | @click="showIncomeTypeSheet = true" |
| | | /> |
| | | @click="showIncomeTypeSheet = true" /> |
| | | <template #right> |
| | | <up-icon name="arrow-right" @click="showIncomeTypeSheet = true"></up-icon> |
| | | <up-icon name="arrow-right" |
| | | @click="showIncomeTypeSheet = true"></up-icon> |
| | | </template> |
| | | </up-form-item> |
| | | </u-cell-group> |
| | | </up-form> |
| | | |
| | | <FooterButtons :loading="loading" confirmText="提交" @cancel="goBack" @confirm="handleSubmit" /> |
| | | |
| | | <up-action-sheet |
| | | :show="showReturnTypeSheet" |
| | | <FooterButtons :loading="loading" |
| | | confirmText="提交" |
| | | @cancel="goBack" |
| | | @confirm="handleSubmit" /> |
| | | <up-action-sheet :show="showReturnTypeSheet" |
| | | title="选择退货方式" |
| | | :actions="returnTypeActions" |
| | | @select="onSelectReturnType" |
| | | @close="showReturnTypeSheet = false" |
| | | /> |
| | | <up-action-sheet |
| | | :show="showProjectPhaseSheet" |
| | | @close="showReturnTypeSheet = false" /> |
| | | <up-action-sheet :show="showProjectPhaseSheet" |
| | | title="选择项目阶段" |
| | | :actions="projectPhaseActions" |
| | | @select="onSelectProjectPhase" |
| | | @close="showProjectPhaseSheet = false" |
| | | /> |
| | | <up-action-sheet |
| | | :show="showSupplierSheet" |
| | | @close="showProjectPhaseSheet = false" /> |
| | | <up-action-sheet :show="showSupplierSheet" |
| | | title="选择供应商" |
| | | :actions="supplierActions" |
| | | @select="onSelectSupplier" |
| | | @close="showSupplierSheet = false" |
| | | /> |
| | | <up-action-sheet |
| | | :show="showPreparedUserSheet" |
| | | @close="showSupplierSheet = false" /> |
| | | <up-action-sheet :show="showPreparedUserSheet" |
| | | title="选择制单人" |
| | | :actions="userActions" |
| | | @select="onSelectPreparedUser" |
| | | @close="showPreparedUserSheet = false" |
| | | /> |
| | | <up-action-sheet |
| | | :show="showReturnUserSheet" |
| | | @close="showPreparedUserSheet = false" /> |
| | | <up-action-sheet :show="showReturnUserSheet" |
| | | title="选择退料人" |
| | | :actions="userActions" |
| | | @select="onSelectReturnUser" |
| | | @close="showReturnUserSheet = false" |
| | | /> |
| | | <up-action-sheet |
| | | :show="showPurchaseLedgerSheet" |
| | | @close="showReturnUserSheet = false" /> |
| | | <up-action-sheet :show="showPurchaseLedgerSheet" |
| | | title="选择采购合同号" |
| | | :actions="purchaseLedgerActions" |
| | | @select="onSelectPurchaseLedger" |
| | | @close="showPurchaseLedgerSheet = false" |
| | | /> |
| | | <up-action-sheet |
| | | :show="showIncomeTypeSheet" |
| | | @close="showPurchaseLedgerSheet = false" /> |
| | | <up-action-sheet :show="showIncomeTypeSheet" |
| | | title="选择收款方式" |
| | | :actions="incomeTypeActions" |
| | | @select="onSelectIncomeType" |
| | | @close="showIncomeTypeSheet = false" |
| | | /> |
| | | <up-datetime-picker |
| | | :show="showPreparedAtPicker" |
| | | @close="showIncomeTypeSheet = false" /> |
| | | <up-datetime-picker :show="showPreparedAtPicker" |
| | | v-model="preparedAtPickerValue" |
| | | mode="date" |
| | | @confirm="onPreparedAtConfirm" |
| | | @cancel="showPreparedAtPicker = false" |
| | | /> |
| | | @cancel="showPreparedAtPicker = false" /> |
| | | </view> |
| | | </template> |
| | | |
| | |
| | | import FooterButtons from "@/components/FooterButtons.vue"; |
| | | import { formatDateToYMD } from "@/utils/ruoyi"; |
| | | import { createPurchaseReturnOrder } from "@/api/procurementManagement/purchaseReturnOrder"; |
| | | import { getOptions, purchaseListPage, productList } from "@/api/procurementManagement/procurementLedger"; |
| | | import { userListNoPageByTenantId } from "@/api/system/user"; |
| | | import { |
| | | getOptions, |
| | | purchaseList, |
| | | } from "@/api/procurementManagement/procurementLedger"; |
| | | import { userListNoPage, userListNoPageByTenantId } from "@/api/system/user"; |
| | | |
| | | const formRef = ref(); |
| | | const loading = ref(false); |
| | |
| | | }); |
| | | |
| | | const rules = { |
| | | returnType: [{ required: true, message: "请选择退货方式", trigger: "change" }], |
| | | supplierId: [{ required: true, message: "请选择供应商", trigger: "change" }], |
| | | preparedAt: [{ required: true, message: "请选择制作日期", trigger: "change" }], |
| | | preparedUserId: [{ required: true, message: "请选择制单人", trigger: "change" }], |
| | | returnUserId: [{ required: true, message: "请选择退料人", trigger: "change" }], |
| | | purchaseLedgerId: [{ required: true, message: "请选择采购合同号", trigger: "change" }], |
| | | totalAmount: [{ required: true, message: "成交金额不能为空", trigger: "change" }], |
| | | incomeType: [{ required: true, message: "请选择收款方式", trigger: "change" }], |
| | | returnType: [ |
| | | { |
| | | validator: (_rule, value, callback) => { |
| | | if ( |
| | | value === 0 || |
| | | value === 1 || |
| | | String(value) === "0" || |
| | | String(value) === "1" |
| | | ) { |
| | | callback(); |
| | | return; |
| | | } |
| | | callback(new Error("请选择退货方式")); |
| | | }, |
| | | trigger: ["change", "blur"], |
| | | }, |
| | | ], |
| | | supplierName: [ |
| | | { |
| | | validator: (_rule, value, callback) => { |
| | | if (value === null || value === undefined) { |
| | | callback(new Error("请选择供应商")); |
| | | return; |
| | | } |
| | | if (String(value).trim() === "") { |
| | | callback(new Error("请选择供应商")); |
| | | return; |
| | | } |
| | | callback(); |
| | | }, |
| | | trigger: ["change", "blur"], |
| | | }, |
| | | ], |
| | | preparedAt: [ |
| | | { required: true, message: "请选择制作日期", trigger: "change" }, |
| | | ], |
| | | preparedUserName: [ |
| | | { |
| | | validator: (_rule, value, callback) => { |
| | | if (value === null || value === undefined) { |
| | | callback(new Error("请选择制单人")); |
| | | return; |
| | | } |
| | | if (String(value).trim() === "") { |
| | | callback(new Error("请选择制单人")); |
| | | return; |
| | | } |
| | | callback(); |
| | | }, |
| | | trigger: ["change", "blur"], |
| | | }, |
| | | ], |
| | | returnUserName: [ |
| | | { |
| | | validator: (_rule, value, callback) => { |
| | | if (value === null || value === undefined) { |
| | | callback(new Error("请选择退料人")); |
| | | return; |
| | | } |
| | | if (String(value).trim() === "") { |
| | | callback(new Error("请选择退料人")); |
| | | return; |
| | | } |
| | | callback(); |
| | | }, |
| | | trigger: ["change", "blur"], |
| | | }, |
| | | ], |
| | | purchaseContractNumber: [ |
| | | { |
| | | validator: (_rule, value, callback) => { |
| | | if (value === null || value === undefined) { |
| | | callback(new Error("请选择采购合同号")); |
| | | return; |
| | | } |
| | | if (String(value).trim() === "") { |
| | | callback(new Error("请选择采购合同号")); |
| | | return; |
| | | } |
| | | callback(); |
| | | }, |
| | | trigger: ["change", "blur"], |
| | | }, |
| | | ], |
| | | totalAmount: [ |
| | | { |
| | | validator: (_rule, value, callback) => { |
| | | if (value === null || value === undefined || value === "") { |
| | | callback(new Error("成交金额不能为空")); |
| | | return; |
| | | } |
| | | const num = Number(value); |
| | | if (Number.isNaN(num)) { |
| | | callback(new Error("成交金额格式不正确")); |
| | | return; |
| | | } |
| | | callback(); |
| | | }, |
| | | trigger: ["change", "blur"], |
| | | }, |
| | | ], |
| | | incomeType: [ |
| | | { required: true, message: "请选择收款方式", trigger: "change" }, |
| | | ], |
| | | }; |
| | | |
| | | const showReturnTypeSheet = ref(false); |
| | |
| | | ]; |
| | | |
| | | const returnTypeText = computed(() => { |
| | | return returnTypeActions.find(i => String(i.value) === String(form.value.returnType))?.name || ""; |
| | | return ( |
| | | returnTypeActions.find( |
| | | i => String(i.value) === String(form.value.returnType) |
| | | )?.name || "" |
| | | ); |
| | | }); |
| | | const projectPhaseText = computed(() => { |
| | | return projectPhaseActions.find(i => String(i.value) === String(form.value.projectPhase))?.name || ""; |
| | | return ( |
| | | projectPhaseActions.find( |
| | | i => String(i.value) === String(form.value.projectPhase) |
| | | )?.name || "" |
| | | ); |
| | | }); |
| | | const supplierText = computed(() => { |
| | | return supplierOptions.value.find(i => String(i.id) === String(form.value.supplierId))?.supplierName || ""; |
| | | return ( |
| | | supplierOptions.value.find( |
| | | i => String(i.id) === String(form.value.supplierId) |
| | | )?.supplierName || "" |
| | | ); |
| | | }); |
| | | const preparedUserText = computed(() => { |
| | | return userOptions.value.find(i => String(i.userId) === String(form.value.preparedUserId))?.nickName || ""; |
| | | return ( |
| | | userOptions.value.find( |
| | | i => String(i.userId) === String(form.value.preparedUserId) |
| | | )?.nickName || "" |
| | | ); |
| | | }); |
| | | const returnUserText = computed(() => { |
| | | return userOptions.value.find(i => String(i.userId) === String(form.value.returnUserId))?.nickName || ""; |
| | | return ( |
| | | userOptions.value.find( |
| | | i => String(i.userId) === String(form.value.returnUserId) |
| | | )?.nickName || "" |
| | | ); |
| | | }); |
| | | const purchaseContractText = computed(() => { |
| | | return purchaseLedgerOptions.value.find(i => String(i.id) === String(form.value.purchaseLedgerId))?.purchaseContractNumber || ""; |
| | | return ( |
| | | purchaseLedgerOptions.value.find( |
| | | i => String(i.id) === String(form.value.purchaseLedgerId) |
| | | )?.purchaseContractNumber || "" |
| | | ); |
| | | }); |
| | | const incomeTypeText = computed(() => { |
| | | return incomeTypeActions.find(i => String(i.value) === String(form.value.incomeType))?.name || ""; |
| | | return ( |
| | | incomeTypeActions.find( |
| | | i => String(i.value) === String(form.value.incomeType) |
| | | )?.name || "" |
| | | ); |
| | | }); |
| | | |
| | | const supplierActions = computed(() => { |
| | | return supplierOptions.value.map(i => ({ name: i.supplierName, value: i.id })); |
| | | return supplierOptions.value.map(i => ({ |
| | | name: i.supplierName, |
| | | value: i.id, |
| | | })); |
| | | }); |
| | | const userActions = computed(() => { |
| | | return userOptions.value.map(i => ({ name: i.nickName, value: i.userId })); |
| | | }); |
| | | const purchaseLedgerActions = computed(() => { |
| | | return purchaseLedgerOptions.value.map(i => ({ name: i.purchaseContractNumber, value: i.id })); |
| | | return purchaseLedgerOptions.value.map(i => ({ |
| | | name: i.purchaseContractNumber, |
| | | value: i.id, |
| | | })); |
| | | }); |
| | | |
| | | const toNumber = val => { |
| | |
| | | |
| | | const baseAmount = computed(() => { |
| | | const rows = form.value.purchaseReturnOrderProductsDtos || []; |
| | | return rows.reduce((sum, item) => sum + toNumber(item.taxInclusiveTotalPrice), 0); |
| | | return rows.reduce( |
| | | (sum, item) => sum + toNumber(item.taxInclusiveTotalPrice), |
| | | 0 |
| | | ); |
| | | }); |
| | | |
| | | const syncTotalAmount = () => { |
| | |
| | | }; |
| | | |
| | | const getReturnQtyMax = row => { |
| | | const qty = Number(row?.quantity); |
| | | const qty = Number(row?.unQuantity ?? row?.quantity); |
| | | if (Number.isNaN(qty) || qty < 0) return 0; |
| | | return qty; |
| | | }; |
| | |
| | | }; |
| | | const onSelectSupplier = action => { |
| | | form.value.supplierId = action.value; |
| | | form.value.supplierName = supplierOptions.value.find(i => String(i.id) === String(action.value))?.supplierName || ""; |
| | | form.value.supplierName = |
| | | supplierOptions.value.find(i => String(i.id) === String(action.value)) |
| | | ?.supplierName || ""; |
| | | form.value.purchaseLedgerId = undefined; |
| | | form.value.purchaseContractNumber = ""; |
| | | form.value.purchaseReturnOrderProductsDtos = []; |
| | |
| | | }; |
| | | const onSelectPreparedUser = action => { |
| | | form.value.preparedUserId = action.value; |
| | | form.value.preparedUserName = userOptions.value.find(i => String(i.userId) === String(action.value))?.nickName || ""; |
| | | form.value.preparedUserName = |
| | | userOptions.value.find(i => String(i.userId) === String(action.value)) |
| | | ?.nickName || ""; |
| | | showPreparedUserSheet.value = false; |
| | | }; |
| | | const onSelectReturnUser = action => { |
| | | form.value.returnUserId = action.value; |
| | | form.value.returnUserName = userOptions.value.find(i => String(i.userId) === String(action.value))?.nickName || ""; |
| | | form.value.returnUserName = |
| | | userOptions.value.find(i => String(i.userId) === String(action.value)) |
| | | ?.nickName || ""; |
| | | showReturnUserSheet.value = false; |
| | | }; |
| | | const onSelectPurchaseLedger = action => { |
| | | form.value.purchaseLedgerId = action.value; |
| | | form.value.purchaseContractNumber = |
| | | purchaseLedgerOptions.value.find(i => String(i.id) === String(action.value))?.purchaseContractNumber || ""; |
| | | purchaseLedgerOptions.value.find(i => String(i.id) === String(action.value)) |
| | | ?.purchaseContractNumber || ""; |
| | | form.value.purchaseReturnOrderProductsDtos = []; |
| | | resetFeeInfo(); |
| | | showPurchaseLedgerSheet.value = false; |
| | |
| | | uni.showToast({ title: "折扣率需在0-100", icon: "none" }); |
| | | return; |
| | | } |
| | | form.value.totalDiscountAmount = Number((baseAmount.value * (rate / 100)).toFixed(2)); |
| | | form.value.totalDiscountAmount = Number( |
| | | (baseAmount.value * (rate / 100)).toFixed(2) |
| | | ); |
| | | syncTotalAmount(); |
| | | }; |
| | | |
| | |
| | | }; |
| | | |
| | | const fetchUserOptions = () => { |
| | | userListNoPageByTenantId() |
| | | return userListNoPageByTenantId() |
| | | .then(res => { |
| | | userOptions.value = res.data || []; |
| | | const rows = res?.data || res?.rows || []; |
| | | if (Array.isArray(rows) && rows.length > 0) { |
| | | userOptions.value = rows; |
| | | return; |
| | | } |
| | | return userListNoPage().then(res2 => { |
| | | const rows2 = res2?.data || res2?.rows || []; |
| | | userOptions.value = Array.isArray(rows2) ? rows2 : []; |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | userOptions.value = []; |
| | | }); |
| | | }; |
| | | |
| | | const ensureUserOptions = async () => { |
| | | if (userOptions.value?.length) return; |
| | | await fetchUserOptions(); |
| | | }; |
| | | |
| | | const openPreparedUserSheet = async () => { |
| | | await ensureUserOptions(); |
| | | showPreparedUserSheet.value = true; |
| | | }; |
| | | |
| | | const openReturnUserSheet = async () => { |
| | | await ensureUserOptions(); |
| | | showReturnUserSheet.value = true; |
| | | }; |
| | | |
| | | const fetchPurchaseLedgerOptions = () => { |
| | | purchaseLedgerOptions.value = []; |
| | | if (!form.value.supplierId) return; |
| | | purchaseListPage({ |
| | | current: -1, |
| | | size: -1, |
| | | supplierId: form.value.supplierId, |
| | | approvalStatus: 3, |
| | | }) |
| | | purchaseList({ supplierId: form.value.supplierId, approvalStatus: 3 }) |
| | | .then(res => { |
| | | purchaseLedgerOptions.value = res?.data?.records || []; |
| | | const rows = res?.rows || res?.data?.records || res?.data || []; |
| | | purchaseLedgerOptions.value = Array.isArray(rows) ? rows : []; |
| | | }) |
| | | .catch(() => { |
| | | purchaseLedgerOptions.value = []; |
| | |
| | | }; |
| | | |
| | | const mergeSelectedProducts = selectedRows => { |
| | | const existing = new Set((form.value.purchaseReturnOrderProductsDtos || []).map(i => String(i.salesLedgerProductId || i.id))); |
| | | const existing = new Set( |
| | | (form.value.purchaseReturnOrderProductsDtos || []).map(i => String(i.id)) |
| | | ); |
| | | const toAdd = (selectedRows || []) |
| | | .filter(i => !existing.has(String(i.id))) |
| | | .map(i => ({ |
| | | ...i, |
| | | salesLedgerProductId: i.id, |
| | | returnQuantity: 0, |
| | | taxInclusiveTotalPrice: 0, |
| | | })); |
| | | form.value.purchaseReturnOrderProductsDtos.push(...toAdd); |
| | | syncTotalAmount(); |
| | | }; |
| | | |
| | | const loadProductsFromPurchaseLedger = () => { |
| | | if (!form.value.purchaseLedgerId) return; |
| | | uni.showLoading({ title: "加载产品...", mask: true }); |
| | | productList({ salesLedgerId: form.value.purchaseLedgerId, type: 2 }) |
| | | .then(res => { |
| | | const rows = res.data || []; |
| | | mergeSelectedProducts(rows); |
| | | }) |
| | | .catch(() => { |
| | | uni.showToast({ title: "加载产品失败", icon: "error" }); |
| | | }) |
| | | .finally(() => { |
| | | uni.hideLoading(); |
| | | }); |
| | | }; |
| | | |
| | | const validateProducts = () => { |
| | |
| | | }); |
| | | const payload = { |
| | | ...form.value, |
| | | purchaseReturnOrderProductsDtos: rows.filter(i => toNumber(i.returnQuantity) > 0), |
| | | purchaseReturnOrderProductsDtos: rows |
| | | .filter(i => toNumber(i.returnQuantity) > 0) |
| | | .map(row => ({ |
| | | ...row, |
| | | stockInRecordId: row.id, |
| | | })), |
| | | }; |
| | | createPurchaseReturnOrder(payload) |
| | | .then(() => { |
| | |
| | | } |
| | | } |
| | | }); |
| | | |
| | | const showAutoLoadModalOnceKey = "purchaseReturnOrderAutoLoadShown"; |
| | | watch( |
| | | () => form.value.purchaseLedgerId, |
| | | (val, oldVal) => { |
| | | if (!val || String(val) === String(oldVal)) return; |
| | | if (uni.getStorageSync(showAutoLoadModalOnceKey)) return; |
| | | uni.setStorageSync(showAutoLoadModalOnceKey, "1"); |
| | | uni.showModal({ |
| | | title: "提示", |
| | | content: "是否自动加载该采购合同下全部产品?", |
| | | success: res => { |
| | | if (res.confirm) loadProductsFromPurchaseLedger(); |
| | | }, |
| | | }); |
| | | } |
| | | ); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import "@/styles/procurement-common.scss"; |
| | | @import "@/static/scss/form-common.scss"; |
| | | |
| | | .account-detail { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | padding-bottom: 90px; |
| | | } |
| | | |
| | | .form-section { |
| | | margin: 12px; |
| | | border-radius: 12px; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .product-actions { |
| | | .section-actions { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | padding: 12px 12px 0 12px; |
| | | } |
| | | |
| | | .amount-summary { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 10px; |
| | | } |
| | | |
| | | .amount-text { |
| | | font-size: 14px; |
| | | color: #333; |
| | | font-weight: 600; |
| | | } |
| | | |
| | | .empty-products { |
| | | padding: 16px 12px; |
| | | color: #999; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .product-list { |
| | | padding: 12px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 12px; |
| | | } |
| | | |
| | | .product-card { |
| | | background: #fff; |
| | | border-radius: 12px; |
| | | padding: 0 12px; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); |
| | | } |
| | | |
| | | .product-header { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | padding: 12px 0; |
| | | } |
| | | |
| | | .product-title { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .product-name { |
| | | font-size: 14px; |
| | | color: #333; |
| | | font-size: 13px; |
| | | color: #2979ff; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .product-body { |
| | | padding: 12px 0; |
| | | } |
| | | |
| | | .qty-row { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | padding: 8px 0; |
| | | } |
| | | |
| | | .qty-label { |
| | | font-size: 12px; |
| | | color: #777; |
| | | .empty-products { |
| | | padding: 8px 0 0 0; |
| | | color: #999; |
| | | font-size: 14px; |
| | | } |
| | | </style> |