feat(approval): 添加审批详情接口和开柜中状态处理

- 新增审批详情接口getApprovalDetailAssetApi
- 添加开柜中状态(4)到状态映射和类型定义
- 重构审批处理页面,支持分步操作和状态判断
- 添加数量确定功能allocateApprovalGoods
- 优化审批流程,支持开柜中状态下的操作
This commit is contained in:
dzq 2025-06-18 15:12:51 +08:00
parent b113afa71f
commit 1224419c9e
4 changed files with 166 additions and 83 deletions

View File

@ -1,5 +1,5 @@
import { request } from '@/http/axios' import { request } from '@/http/axios'
import { SubmitApprovalRequestData, SubmitApprovalResponseData, SearchApiReturnApprovalQuery, ApiResponsePageData, ReturnApprovalEntity, HandleApprovalRequestData, SearchReturnApprovalAssetQuery, ReturnApprovalAssetDTO, HandleApprovalAssetRequestData, ApprovalGoodsCellEntity } from './type' import { SubmitApprovalRequestData, SubmitApprovalResponseData, SearchApiReturnApprovalQuery, ApiResponsePageData, ReturnApprovalEntity, HandleApprovalRequestData, SearchReturnApprovalAssetQuery, ReturnApprovalAssetDTO, HandleApprovalAssetRequestData, ApprovalGoodsCellEntity, ReturnApprovalDetailDTO } from './type'
import { OpenCabinetApiData, ShopOrderGoodsEntity } from '../shop/type' import { OpenCabinetApiData, ShopOrderGoodsEntity } from '../shop/type'
export const getApprovalListApi = (params: SearchApiReturnApprovalQuery) => { export const getApprovalListApi = (params: SearchApiReturnApprovalQuery) => {
@ -50,7 +50,7 @@ export const handleApprovalApi = (data: HandleApprovalRequestData) => {
} }
export const handleApprovalAssetApi = (data: HandleApprovalAssetRequestData) => { export const handleApprovalAssetApi = (data: HandleApprovalRequestData) => {
return request<ApiResponseMsgData<string>>({ return request<ApiResponseMsgData<string>>({
url: 'approval/handle/asset', url: 'approval/handle/asset',
method: 'post', method: 'post',
@ -58,6 +58,14 @@ export const handleApprovalAssetApi = (data: HandleApprovalAssetRequestData) =>
}) })
} }
export const allocateApprovalGoods = (data: HandleApprovalAssetRequestData) => {
return request<ApiResponseMsgData<string>>({
url: 'approval/handle/allocateApprovalGoods',
method: 'post',
data
})
}
export const getApprovalOrderGoodsApi = (approvalId: number) => { export const getApprovalOrderGoodsApi = (approvalId: number) => {
return request<ApiResponseMsgData<ShopOrderGoodsEntity[]>>({ return request<ApiResponseMsgData<ShopOrderGoodsEntity[]>>({
url: 'approval/getApprovalOrderGoods', url: 'approval/getApprovalOrderGoods',
@ -67,11 +75,23 @@ export const getApprovalOrderGoodsApi = (approvalId: number) => {
} }
export const getApprovalGoodsCellApi = (approvalId: number) => { export const getApprovalGoodsCellApi = (approvalId: number) => {
return request<ApiResponseMsgData<ApprovalGoodsCellEntity[]>>({ return request<ApiResponseMsgData<ApprovalGoodsCellEntity[]>>(
url: 'approval/getApprovalGoodsCell', {
method: 'get', url: 'approval/getApprovalGoodsCell',
params: { approvalId } method: 'get',
}) params: { approvalId }
}
)
}
export const getApprovalDetailAssetApi = (approvalId: number) => {
return request<ApiResponseMsgData<ReturnApprovalDetailDTO>>(
{
url: 'approval/detail/asset',
method: 'get',
params: { approval_id: approvalId }
}
)
} }
/** 打开储物柜接口 */ /** 打开储物柜接口 */

View File

@ -94,7 +94,7 @@ export interface ReturnApprovalEntity {
auditRemark: string auditRemark: string
/** 审批人姓名 */ /** 审批人姓名 */
auditName: string auditName: string
/** 审批状态(1待审核 2已通过 3已驳回) */ /** 审批状态(1待审核 2已通过 3已驳回 4开柜中) */
status: number status: number
/** 审批时间 */ /** 审批时间 */
approvalTime?: string approvalTime?: string
@ -134,6 +134,11 @@ export interface ReturnApprovalAssetDTO extends ReturnApprovalEntity {
goodsList?: ApprovalGoodsEntity[]; goodsList?: ApprovalGoodsEntity[];
} }
export interface ReturnApprovalDetailDTO extends ReturnApprovalAssetDTO {
statusStr: string;
approvalGoodsCellList?: ApprovalGoodsCellEntity[];
}
export interface SearchReturnApprovalAssetQuery { export interface SearchReturnApprovalAssetQuery {
pageNum: number; pageNum: number;
pageSize: number; pageSize: number;

View File

@ -2,14 +2,15 @@
import { ref, onMounted, computed } from 'vue' import { ref, onMounted, computed } from 'vue'
import { showConfirmDialog, showDialog, UploaderFileListItem, Popup, Picker, Field, Stepper } from 'vant' import { showConfirmDialog, showDialog, UploaderFileListItem, Popup, Picker, Field, Stepper } from 'vant'
import axios from "axios" import axios from "axios"
import { getApprovalGoodsCellApi, handleApprovalApi, handleApprovalAssetApi, openCabinetApi } from '@/common/apis/approval' import { allocateApprovalGoods, getApprovalGoodsCellApi, handleApprovalApi, handleApprovalAssetApi, openCabinetApi } from '@/common/apis/approval'
import type { ApprovalGoodsCellEntity, ApprovalGoodsEntity, HandleApprovalAssetRequestData, HandleApprovalRequestData } from '@/common/apis/approval/type' import type { ApprovalGoodsCellEntity, ApprovalGoodsEntity, HandleApprovalAssetRequestData, HandleApprovalRequestData, ReturnApprovalDetailDTO } from '@/common/apis/approval/type'
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import { useApprovalStore } from '@/pinia/stores/approval' import { useApprovalStore } from '@/pinia/stores/approval'
import { useWxStore } from '@/pinia/stores/wx'; import { useWxStore } from '@/pinia/stores/wx';
import { getApprovalDetailAssetApi } from '@/common/apis/approval';
import Compressor from 'compressorjs'; import Compressor from 'compressorjs';
import { useAb98UserStore } from '@/pinia/stores/ab98-user' import { useAb98UserStore } from '@/pinia/stores/ab98-user';
import { ShopOrderGoodsEntity } from '@/common/apis/shop/type' import { ShopOrderGoodsEntity } from '@/common/apis/shop/type';
const { VITE_APP_BASE_API } = import.meta.env; const { VITE_APP_BASE_API } = import.meta.env;
const router = useRouter() const router = useRouter()
@ -20,6 +21,8 @@ const { openid, balance, corpidLogin, userid: qyUserid, name: qyName } = storeTo
const ab98UserStore = useAb98UserStore(); const ab98UserStore = useAb98UserStore();
const { tel, userid: ab98Userid, name } = storeToRefs(ab98UserStore); const { tel, userid: ab98Userid, name } = storeToRefs(ab98UserStore);
const detailData = ref<ReturnApprovalDetailDTO>();
const formData = ref<HandleApprovalAssetRequestData>({ const formData = ref<HandleApprovalAssetRequestData>({
approvalId: approvalStore.currentApproval?.approvalId || 0, approvalId: approvalStore.currentApproval?.approvalId || 0,
status: 2, status: 2,
@ -61,9 +64,9 @@ const validateForm = () => {
showConfirmDialog({ title: '提示', message: '驳回时必须填写审核说明' }) showConfirmDialog({ title: '提示', message: '驳回时必须填写审核说明' })
return false return false
} }
// //
if (approvalStore.currentApproval?.status === 1) { if (detailData.value?.status === 1) {
for (const item of orderGoods.value) { for (const item of orderGoods.value) {
if (item.approvalQuantity != null && item.approvalQuantity < 0) { if (item.approvalQuantity != null && item.approvalQuantity < 0) {
showConfirmDialog({ title: '提示', message: `商品${item.goodsName}的审批数量不能为负数` }) showConfirmDialog({ title: '提示', message: `商品${item.goodsName}的审批数量不能为负数` })
@ -104,51 +107,53 @@ const previewImage = (url: string) => {
const approvalGoodsCells = ref<ApprovalGoodsCellEntity[]>([]); const approvalGoodsCells = ref<ApprovalGoodsCellEntity[]>([]);
const approvalGoodsCellsWithNames = computed(() => { const approvalGoodsCellsWithNames = computed(() => {
return approvalGoodsCells.value.map(cell => { return approvalGoodsCells.value.map(cell => {
const goods = orderGoods.value.find(g => g.approvalGoodsId === cell.approvalGoodsId); const goods = orderGoods.value.find(g => g.approvalGoodsId === cell.approvalGoodsId);
return { return {
...cell, ...cell,
goodsName: goods ? goods.goodsName : '' goodsName: goods ? goods.goodsName : ''
}; };
}); });
}); });
onMounted(async () => { const fetchApprovalDetail = async () => {
if (!approvalStore.currentApproval) { const approvalId = approvalStore.currentApproval?.approvalId
if (!approvalId) {
router.push('/approvalAsset/list'); router.push('/approvalAsset/list');
return; return;
} }
// approvalQuantity try {
orderGoods.value = (approvalStore.currentApproval.goodsList || []).map(item => ({ const result = await getApprovalDetailAssetApi(approvalId);
...item, if (result.code === 0) {
approvalQuantity: approvalStore.currentApproval?.status === 1 ? item.applyQuantity : item.approvalQuantity detailData.value = result.data;
})); orderGoods.value = (result.data.goodsList || []).map(item => ({
...item,
approvalQuantity: result.data.status === 1 ? item.applyQuantity : item.approvalQuantity
}));
if (approvalStore.currentApproval.status !== 1) { if (result.data.status !== 1) {
// formData.value = {
formData.value = { ...formData.value,
...formData.value, corpid: wxStore.corpid,
corpid: wxStore.corpid, status: result.data.status,
status: approvalStore.currentApproval.status, returnAmount: result.data.returnAmount,
returnAmount: approvalStore.currentApproval.returnAmount, auditRemark: result.data.auditRemark,
auditRemark: approvalStore.currentApproval.auditRemark, auditImages: result.data.auditImages
auditImages: approvalStore.currentApproval.auditImages };
}; approvalGoodsCells.value = result.data.approvalGoodsCellList || [];
//
try {
const result = await getApprovalGoodsCellApi(approvalStore.currentApproval.approvalId);
if (result.code === 0) {
approvalGoodsCells.value = result.data;
} else {
showDialog({ title: '错误', message: result.msg || '获取审批商品格口信息失败' });
} }
} catch (error) { } else {
console.error('获取审批商品格口信息失败:', error); showDialog({ title: '错误', message: result.msg || '获取审批详情失败' });
showDialog({ title: '错误', message: '获取审批商品格口信息失败' });
} }
} catch (error) {
console.error('获取审批详情失败:', error);
showDialog({ title: '错误', message: '获取审批详情失败' });
} }
}
onMounted(async () => {
await fetchApprovalDetail();
}) })
const handleOpenCell = async (approvalGoodsCellId: number) => { const handleOpenCell = async (approvalGoodsCellId: number) => {
@ -186,21 +191,6 @@ const handleOpenCell = async (approvalGoodsCellId: number) => {
const handleSubmit = async () => { const handleSubmit = async () => {
if (!validateForm()) return if (!validateForm()) return
// approvalGoodsList
formData.value.approvalGoodsList = orderGoods.value.map(item => ({
approvalGoodsId: item.approvalGoodsId || 0,
approvalId: formData.value.approvalId,
goodsId: item.goodsId,
goodsName: item.goodsName,
externalGoodsId: item.externalGoodsId,
corpid: item.corpid,
belongType: item.belongType,
price: item.price,
applyQuantity: item.applyQuantity,
approvalQuantity: item.approvalQuantity,
coverImg: item.coverImg
}))
submitting.value = true submitting.value = true
try { try {
formData.value.userid = wxStore.userid; formData.value.userid = wxStore.userid;
@ -239,6 +229,53 @@ const handleComfirm = () => {
handleSubmit(); handleSubmit();
} }
const handleAllocateQuantity = async () => {
if (!validateForm()) return
// approvalGoodsList
formData.value.approvalGoodsList = orderGoods.value.map(item => ({
approvalGoodsId: item.approvalGoodsId || 0,
approvalId: formData.value.approvalId,
goodsId: item.goodsId,
goodsName: item.goodsName,
externalGoodsId: item.externalGoodsId,
corpid: item.corpid,
belongType: item.belongType,
price: item.price,
applyQuantity: item.applyQuantity,
approvalQuantity: item.approvalQuantity,
coverImg: item.coverImg
}))
submitting.value = true
try {
formData.value.userid = wxStore.userid;
formData.value.corpid = wxStore.corpid;
formData.value.auditUserid = wxStore.userid;
const { code, msg } = await allocateApprovalGoods(formData.value)
if (code === 0) {
showDialog({ message: '数量确定成功' })
await fetchApprovalDetail();
} else {
console.error('操作失败code:', code, 'msg:', msg)
showConfirmDialog({
title: '操作失败',
message: msg || '数量确定失败'
})
}
} catch (error) {
console.error('提交失败:', error)
showConfirmDialog({
title: '提交失败',
message: error instanceof Error ? error.message : '网络请求异常'
})
} finally {
submitting.value = false
}
}
const handleReject = () => { const handleReject = () => {
formData.value.status = 3; formData.value.status = 3;
handleSubmit(); handleSubmit();
@ -252,9 +289,8 @@ const handleReject = () => {
<div class="content-wrapper"> <div class="content-wrapper">
<van-cell-group> <van-cell-group>
<van-cell title="申请人" :value="approvalStore.currentApproval?.applyUserName" /> <van-cell title="申请人" :value="detailData?.applyUserName" />
<van-cell title="当前状态" :value="statusMap[approvalStore.currentApproval?.status || 1]" /> <van-cell title="当前状态" :value="statusMap[detailData?.status || 1]" />
<!-- <van-cell title="领用说明" :value="approvalStore.currentApproval?.applyRemark" /> -->
</van-cell-group> </van-cell-group>
<van-cell-group class="product-list"> <van-cell-group class="product-list">
@ -277,26 +313,27 @@ const handleReject = () => {
</span> </span>
</div> </div>
<!-- 审批数量输入框 --> <!-- 审批数量输入框 -->
<div v-if="approvalStore.currentApproval?.status === 1" class="approval-quantity"> <div v-if="detailData?.status === 1" class="approval-quantity">
<span class="label">审批数量:</span> <span class="label">审批数量:</span>
<van-stepper <van-stepper v-model.number="item.approvalQuantity" :min="0" :max="item.applyQuantity"
v-model.number="item.approvalQuantity" integer style="width: 180px;" />
:min="0"
:max="item.applyQuantity"
integer
style="width: 180px;"
/>
</div> </div>
<!-- 查看审批数量 --> <!-- 查看审批数量 -->
<div v-if="approvalStore.currentApproval?.status === 2" class="approval-quantity-view"> <div v-if="detailData?.status === 2 || detailData?.status === 4"
class="approval-quantity-view">
<span class="label">审批数量:</span> <span class="label">审批数量:</span>
<span class="value">{{ item.approvalQuantity }}</span> <span class="value">{{ item.approvalQuantity }}</span>
</div> </div>
</div> </div>
</van-cell> </van-cell>
</template> </template>
<div class="confirm-quantity-container">
<van-button class="confirm-quantity-btn" v-if="detailData?.status === 1" type="primary"
@click="handleAllocateQuantity" :loading="submitting" plain hairline size="small">
确定审批数量
</van-button>
</div>
</van-cell-group> </van-cell-group>
<van-cell-group class="approval-goods-list" v-if="approvalGoodsCells.length > 0"> <van-cell-group class="approval-goods-list" v-if="approvalGoodsCells.length > 0">
<van-cell title="审批通过商品:" class="section-title" /> <van-cell title="审批通过商品:" class="section-title" />
<template v-for="item in approvalGoodsCellsWithNames" :key="item.approvalGoodsCellId"> <template v-for="item in approvalGoodsCellsWithNames" :key="item.approvalGoodsCellId">
@ -314,8 +351,9 @@ const handleReject = () => {
<div class="van-ellipsis"> <div class="van-ellipsis">
分配数量{{ item.allocateQuantity }} 分配数量{{ item.allocateQuantity }}
</div> </div>
<div class="open-cell-btn"> <div v-if="detailData?.status === 4" class="open-cell-btn">
<van-button type="primary" size="small" @click="handleOpenCell(item.approvalGoodsCellId)" :disabled="isButtonDisabled"> <van-button type="primary" size="small"
@click="handleOpenCell(item.approvalGoodsCellId)" :disabled="isButtonDisabled">
打开格口 打开格口
</van-button> </van-button>
</div> </div>
@ -341,12 +379,13 @@ const handleReject = () => {
</div> </div>
</van-popup> </van-popup>
<div class="btn-group" v-if="approvalStore.currentApproval?.status === 1"> <div class="btn-group" v-if="detailData?.status === 1 || detailData?.status === 4">
<van-button type="danger" :loading="submitting" loading-text="提交中..." @click="handleReject" <van-button type="danger" :loading="submitting" loading-text="提交中..." @click="handleReject"
style="flex: 1; height: 44px; border-radius: 8px; font-size: 16px;"> style="flex: 1; height: 44px; border-radius: 8px; font-size: 16px;">
拒绝 拒绝
</van-button> </van-button>
<van-button type="primary" :loading="submitting" loading-text="提交中..." @click="handleComfirm" <van-button type="primary" :disabled="detailData?.status === 1" :loading="submitting"
loading-text="提交中..." @click="handleComfirm"
style="flex: 1; height: 44px; border-radius: 8px; font-size: 16px;"> style="flex: 1; height: 44px; border-radius: 8px; font-size: 16px;">
同意 同意
</van-button> </van-button>
@ -411,6 +450,7 @@ const handleReject = () => {
.approval-quantity-view { .approval-quantity-view {
justify-content: flex-end; justify-content: flex-end;
} }
.price-row { .price-row {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
@ -465,6 +505,23 @@ const handleReject = () => {
padding: 16px; padding: 16px;
} }
.confirm-quantity-container {
display: flex;
justify-content: flex-end;
margin-top: 8px;
}
.confirm-quantity-btn {
margin-bottom: 8px;
margin-right: 8px;
height: 36px;
width: 140px;
border-radius: 8px;
font-size: 16px;
padding: 0 20px;
}
.content-wrapper { .content-wrapper {
padding-bottom: 100px; padding-bottom: 100px;
} }
@ -490,4 +547,4 @@ const handleReject = () => {
background-color: #ebedf0; background-color: #ebedf0;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
} }
</style> </style>

View File

@ -79,7 +79,8 @@ const statusOptions = [
const statusMap: { [key: number]: string } = { const statusMap: { [key: number]: string } = {
1: '待审核', 1: '待审核',
2: '已通过', 2: '已通过',
3: '已驳回' 3: '已驳回',
4: '开柜中'
} }
const statusText = ref('') const statusText = ref('')