Files
crm_uiapp/src/pages-erp/purchase-in/detail/index.vue

418 lines
14 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="yd-page-container">
<!-- 顶部导航栏 -->
<wd-navbar
title="采购入库详情"
left-arrow placeholder safe-area-inset-top fixed
@click-left="handleBack"
/>
<!-- 详情内容 -->
<view v-if="formData">
<!-- 基本信息 -->
<wd-cell-group title="基本信息" border>
<wd-cell title="入库单编号" :value="formData.no" />
<wd-cell title="审核状态">
<view
class="rounded-8rpx px-16rpx py-4rpx text-24rpx"
:class="getStatusClass(formData.status, formData.isQualified)"
>
{{ getStatusText(formData.status, formData.isQualified) }}
</view>
</wd-cell>
<wd-cell title="供应商" :value="formData.supplierName || '-'" />
<wd-cell title="入库时间" :value="formatDateTime(formData.inTime)" />
<wd-cell title="关联订单" :value="formData.orderNo || '-'" />
<wd-cell title="创建人" :value="formData.creatorName || '-'" />
<wd-cell title="创建时间" :value="formatDateTime(formData.createTime)" />
</wd-cell-group>
<!-- 金额信息 -->
<wd-cell-group title="金额信息" border>
<wd-cell title="合计数量" :value="String(formData.totalCount || 0)" />
<wd-cell title="合计产品价格" :value="`¥${formData.totalProductPrice || 0}`" />
<wd-cell title="合计税额" :value="`¥${formData.totalTaxPrice || 0}`" />
<wd-cell title="优惠率" :value="`${formData.discountPercent || 0}%`" />
<wd-cell title="优惠金额" :value="`¥${formData.discountPrice || 0}`" />
<wd-cell title="其他费用" :value="`¥${formData.otherPrice || 0}`" />
<wd-cell title="应付金额">
<text class="text-[#e6a23c] font-semibold">¥{{ formData.totalPrice || 0 }}</text>
</wd-cell>
<wd-cell title="已付金额">
<text class="text-[#52c41a] font-semibold">¥{{ formData.paymentPrice || 0 }}</text>
</wd-cell>
<wd-cell title="未付金额">
<text
class="font-semibold"
:class="(formData.totalPrice || 0) - (formData.paymentPrice || 0) > 0 ? 'text-[#f5222d]' : 'text-[#999]'"
>
¥{{ (formData.totalPrice || 0) - (formData.paymentPrice || 0) }}
</text>
</wd-cell>
</wd-cell-group>
<!-- 不合格信息 -->
<wd-cell-group v-if="formData.status !== 10 && !formData.isQualified" title="不合格信息" border>
<wd-cell title="返回方式" :value="getReturnTypeLabel(formData.returnType)" />
<wd-cell v-if="formData.returnRemark" title="返回备注" :value="formData.returnRemark" />
</wd-cell-group>
<!-- 入库明细 -->
<view class="mx-24rpx mt-24rpx">
<view class="mb-16rpx text-32rpx text-[#333] font-semibold">
入库明细{{ formData.items?.length || 0 }}
</view>
<view v-if="formData.items && formData.items.length > 0">
<view
v-for="(item, index) in formData.items"
:key="item.id || index"
class="mb-16rpx overflow-hidden rounded-12rpx bg-white shadow-sm"
>
<!-- 产品头部 -->
<view class="flex items-center justify-between bg-[#f8f8f8] px-24rpx py-16rpx">
<view class="flex items-center">
<text class="text-28rpx text-[#333] font-semibold">{{ item.productName || '-' }}</text>
<text v-if="item.productBarCode" class="ml-12rpx text-22rpx text-[#999]">{{ item.productBarCode }}</text>
</view>
<view class="flex items-center">
<text v-if="item.warehouseName" class="text-24rpx text-[#1890ff]">{{ item.warehouseName }}</text>
<text v-if="item.locationCode" class="ml-8rpx text-22rpx text-[#52c41a]">[{{ item.locationCode }}]</text>
</view>
</view>
<view class="p-24rpx">
<!-- 批次号 -->
<view v-if="item.batchNo" class="mb-12rpx flex items-center text-26rpx text-[#666]">
<text class="mr-8rpx text-[#999]">批次号</text>
<text class="text-[#e6a23c]">{{ item.batchNo }}</text>
</view>
<!-- 产品规格 -->
<view v-if="item.productSpec" class="mb-12rpx flex items-center text-26rpx text-[#666]">
<text class="mr-8rpx text-[#999]">规格</text>
<text>{{ item.productSpec }}</text>
</view>
<!-- 单价 / 数量 / 单位 -->
<view class="mb-12rpx flex items-center text-26rpx text-[#666]">
<view class="mr-24rpx flex items-center">
<text class="mr-8rpx text-[#999]">单价</text>
<text class="text-[#f5222d]">¥{{ item.productPrice || 0 }}</text>
</view>
<view class="mr-24rpx flex items-center">
<text class="mr-8rpx text-[#999]">数量</text>
<text class="font-semibold">{{ item.count || 0 }}</text>
</view>
<view class="flex items-center">
<text class="mr-8rpx text-[#999]">单位</text>
<text>{{ item.productUnitName || '-' }}</text>
</view>
</view>
<!-- 税率 / 税额 -->
<view v-if="item.taxPercent" class="mb-12rpx flex items-center text-26rpx text-[#666]">
<view class="mr-24rpx flex items-center">
<text class="mr-8rpx text-[#999]">税率</text>
<text>{{ item.taxPercent }}%</text>
</view>
<view class="flex items-center">
<text class="mr-8rpx text-[#999]">税额</text>
<text>¥{{ item.taxPrice || 0 }}</text>
</view>
</view>
<!-- 金额 / 库存 -->
<view class="mb-12rpx flex items-center justify-between text-26rpx text-[#666]">
<view class="flex items-center">
<text class="mr-8rpx text-[#999]">金额</text>
<text class="text-[#e6a23c]">¥{{ item.totalPrice || 0 }}</text>
</view>
<view class="flex items-center">
<text class="mr-8rpx text-[#999]">库存</text>
<text>{{ item.stockCount || 0 }}</text>
</view>
</view>
<!-- 备注 -->
<view v-if="item.remark" class="text-24rpx text-[#999]">
备注{{ item.remark }}
</view>
</view>
</view>
</view>
<view v-else class="py-60rpx text-center text-28rpx text-[#999]">
暂无入库明细
</view>
</view>
<!-- 备注 -->
<wd-cell-group v-if="formData.remark" title="备注" border>
<wd-cell :value="formData.remark" />
</wd-cell-group>
</view>
<!-- 底部操作按钮 -->
<view class="yd-detail-footer">
<view class="yd-detail-footer-actions">
<wd-button
v-if="hasAccessByCodes(['erp:purchase-in:update']) && formData?.status === 10"
class="flex-1" type="warning" @click="handleEdit"
>
编辑
</wd-button>
<wd-button
v-if="hasAccessByCodes(['erp:purchase-in:update-status']) && formData?.status === 10"
class="flex-1" type="success" @click="handleAudit"
>
审核
</wd-button>
<wd-button
v-if="hasAccessByCodes(['erp:purchase-in:update-status']) && (formData?.status === 20 || formData?.status === 30)"
class="flex-1" type="warning" @click="handleReverseAudit"
>
反审核
</wd-button>
<wd-button
v-if="hasAccessByCodes(['erp:purchase-in:delete']) && formData?.status === 10"
class="flex-1" type="error" :loading="deleting" @click="handleDelete"
>
删除
</wd-button>
</view>
</view>
<!-- 审核弹窗 -->
<wd-popup v-model="auditVisible" position="bottom" closable @close="auditVisible = false">
<view class="p-32rpx">
<view class="mb-32rpx text-center text-32rpx text-[#333] font-semibold">
采购入库审核
</view>
<view class="mb-24rpx">
<view class="mb-12rpx text-26rpx text-[#666]">
是否合格
</view>
<wd-switch v-model="auditForm.isQualified" @change="handleQualifiedChange" />
</view>
<view v-if="!auditForm.isQualified" class="mb-24rpx">
<view class="mb-12rpx text-26rpx text-[#666]">
返回方式
</view>
<wd-radio-group v-model="auditForm.returnType" shape="button">
<wd-radio
v-for="opt in RETURN_TYPE_OPTIONS"
:key="opt.value"
:value="opt.value"
>
{{ opt.label }}
</wd-radio>
</wd-radio-group>
</view>
<view v-if="!auditForm.isQualified" class="mb-24rpx">
<view class="mb-12rpx text-26rpx text-[#666]">
返回备注
</view>
<wd-textarea
v-model="auditForm.returnRemark"
placeholder="请输入返回方式备注"
:maxlength="200"
/>
</view>
<view class="mt-32rpx flex gap-24rpx">
<wd-button class="flex-1" plain @click="auditVisible = false">
取消
</wd-button>
<wd-button class="flex-1" type="primary" :loading="auditLoading" @click="submitAudit">
确定
</wd-button>
</view>
</view>
</wd-popup>
</view>
</template>
<script lang="ts" setup>
import type { PurchaseIn } from '@/api/erp/purchase-in'
import { onMounted, reactive, ref } from 'vue'
import { useToast } from 'wot-design-uni'
import { deletePurchaseIn, getPurchaseIn, RETURN_TYPE_OPTIONS, updatePurchaseInStatus } from '@/api/erp/purchase-in'
import { useAccess } from '@/hooks/useAccess'
import { navigateBackPlus } from '@/utils'
import { formatDateTime } from '@/utils/date'
const props = defineProps<{
id?: number | any
}>()
definePage({
style: {
navigationBarTitleText: '',
navigationStyle: 'custom',
},
})
const { hasAccessByCodes } = useAccess()
const toast = useToast()
const formData = ref<PurchaseIn>()
const deleting = ref(false)
// 审核相关
const auditVisible = ref(false)
const auditLoading = ref(false)
const auditForm = reactive({
isQualified: true,
returnType: undefined as string | undefined,
returnRemark: undefined as string | undefined,
})
/** 获取状态文本 */
function getStatusText(status?: number, isQualified?: boolean) {
if (status === 10)
return '未审核'
if (status === 20)
return isQualified ? '已审核' : '不合格'
if (status === 30)
return '不合格'
return '未知'
}
/** 获取状态样式 */
function getStatusClass(status?: number, isQualified?: boolean) {
if (status === 10)
return 'bg-[#fff7e6] text-[#fa8c16]'
if (status === 20)
return isQualified ? 'bg-[#f6ffed] text-[#52c41a]' : 'bg-[#fff1f0] text-[#f5222d]'
if (status === 30)
return 'bg-[#fff1f0] text-[#f5222d]'
return 'bg-[#f5f5f5] text-[#999]'
}
/** 获取返回方式标签 */
function getReturnTypeLabel(value?: string | null) {
if (!value)
return '-'
const option = RETURN_TYPE_OPTIONS.find(opt => opt.value === value)
return option ? option.label : value
}
/** 返回上一页 */
function handleBack() {
navigateBackPlus('/pages-erp/purchase-in/index')
}
/** 加载详情 */
async function getDetail() {
if (!props.id) {
return
}
try {
toast.loading('加载中...')
formData.value = await getPurchaseIn(props.id)
} finally {
toast.close()
}
}
/** 编辑操作 */
function handleEdit() {
uni.navigateTo({
url: `/pages-erp/purchase-in/form/index?id=${props.id}`,
})
}
/** 打开审核弹窗 */
function handleAudit() {
auditForm.isQualified = true
auditForm.returnType = undefined
auditForm.returnRemark = undefined
auditVisible.value = true
}
/** 合格状态变化 */
function handleQualifiedChange(val: boolean) {
if (val) {
auditForm.returnType = undefined
auditForm.returnRemark = undefined
}
}
/** 提交审核 */
async function submitAudit() {
if (!props.id)
return
if (!auditForm.isQualified && !auditForm.returnType) {
toast.warning('请选择返回方式')
return
}
auditLoading.value = true
try {
await updatePurchaseInStatus({
id: props.id,
isQualified: auditForm.isQualified,
returnType: auditForm.returnType,
returnRemark: auditForm.returnRemark,
status: auditForm.isQualified ? 20 : 30,
})
toast.success('审核成功')
auditVisible.value = false
getDetail()
} finally {
auditLoading.value = false
}
}
/** 反审核操作 */
function handleReverseAudit() {
if (!props.id) {
return
}
uni.showModal({
title: '提示',
content: '确定要反审核该入库单吗?',
success: async (res) => {
if (!res.confirm) {
return
}
try {
await updatePurchaseInStatus({
id: props.id,
isQualified: false,
status: 10,
})
toast.success('反审核成功')
getDetail()
} catch {
// error handled by http
}
},
})
}
/** 删除操作 */
function handleDelete() {
if (!props.id) {
return
}
uni.showModal({
title: '提示',
content: '确定要删除该采购入库单吗?',
success: async (res) => {
if (!res.confirm) {
return
}
deleting.value = true
try {
await deletePurchaseIn([props.id])
toast.success('删除成功')
setTimeout(() => {
handleBack()
}, 500)
} finally {
deleting.value = false
}
},
})
}
/** 初始化 */
onMounted(() => {
getDetail()
})
</script>
<style lang="scss" scoped>
</style>