From 1224419c9e640b398f2711a6799eb38b1d9bc578 Mon Sep 17 00:00:00 2001 From: dzq <dzq@ys.com> Date: Wed, 18 Jun 2025 15:12:51 +0800 Subject: [PATCH] =?UTF-8?q?feat(approval):=20=E6=B7=BB=E5=8A=A0=E5=AE=A1?= =?UTF-8?q?=E6=89=B9=E8=AF=A6=E6=83=85=E6=8E=A5=E5=8F=A3=E5=92=8C=E5=BC=80?= =?UTF-8?q?=E6=9F=9C=E4=B8=AD=E7=8A=B6=E6=80=81=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增审批详情接口getApprovalDetailAssetApi - 添加开柜中状态(4)到状态映射和类型定义 - 重构审批处理页面,支持分步操作和状态判断 - 添加数量确定功能allocateApprovalGoods - 优化审批流程,支持开柜中状态下的操作 --- src/common/apis/approval/index.ts | 34 ++++- src/common/apis/approval/type.ts | 7 +- src/pages/approval/handleApply.vue | 205 ++++++++++++++++++----------- src/pages/approvalAsset/list.vue | 3 +- 4 files changed, 166 insertions(+), 83 deletions(-) diff --git a/src/common/apis/approval/index.ts b/src/common/apis/approval/index.ts index a7c63eb..3271ef1 100644 --- a/src/common/apis/approval/index.ts +++ b/src/common/apis/approval/index.ts @@ -1,5 +1,5 @@ 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' 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>>({ url: 'approval/handle/asset', 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) => { return request<ApiResponseMsgData<ShopOrderGoodsEntity[]>>({ url: 'approval/getApprovalOrderGoods', @@ -67,11 +75,23 @@ export const getApprovalOrderGoodsApi = (approvalId: number) => { } export const getApprovalGoodsCellApi = (approvalId: number) => { - return request<ApiResponseMsgData<ApprovalGoodsCellEntity[]>>({ - url: 'approval/getApprovalGoodsCell', - method: 'get', - params: { approvalId } - }) + return request<ApiResponseMsgData<ApprovalGoodsCellEntity[]>>( + { + url: 'approval/getApprovalGoodsCell', + method: 'get', + params: { approvalId } + } + ) +} + +export const getApprovalDetailAssetApi = (approvalId: number) => { + return request<ApiResponseMsgData<ReturnApprovalDetailDTO>>( + { + url: 'approval/detail/asset', + method: 'get', + params: { approval_id: approvalId } + } + ) } /** 打开储物柜接口 */ diff --git a/src/common/apis/approval/type.ts b/src/common/apis/approval/type.ts index 8ea159e..983976d 100644 --- a/src/common/apis/approval/type.ts +++ b/src/common/apis/approval/type.ts @@ -94,7 +94,7 @@ export interface ReturnApprovalEntity { auditRemark: string /** 审批人姓名 */ auditName: string - /** 审批状态(1待审核 2已通过 3已驳回) */ + /** 审批状态(1待审核 2已通过 3已驳回 4开柜中) */ status: number /** 审批时间 */ approvalTime?: string @@ -134,6 +134,11 @@ export interface ReturnApprovalAssetDTO extends ReturnApprovalEntity { goodsList?: ApprovalGoodsEntity[]; } +export interface ReturnApprovalDetailDTO extends ReturnApprovalAssetDTO { + statusStr: string; + approvalGoodsCellList?: ApprovalGoodsCellEntity[]; +} + export interface SearchReturnApprovalAssetQuery { pageNum: number; pageSize: number; diff --git a/src/pages/approval/handleApply.vue b/src/pages/approval/handleApply.vue index 54a4bb4..1167172 100644 --- a/src/pages/approval/handleApply.vue +++ b/src/pages/approval/handleApply.vue @@ -2,14 +2,15 @@ import { ref, onMounted, computed } from 'vue' import { showConfirmDialog, showDialog, UploaderFileListItem, Popup, Picker, Field, Stepper } from 'vant' import axios from "axios" -import { getApprovalGoodsCellApi, handleApprovalApi, handleApprovalAssetApi, openCabinetApi } from '@/common/apis/approval' -import type { ApprovalGoodsCellEntity, ApprovalGoodsEntity, HandleApprovalAssetRequestData, HandleApprovalRequestData } from '@/common/apis/approval/type' +import { allocateApprovalGoods, getApprovalGoodsCellApi, handleApprovalApi, handleApprovalAssetApi, openCabinetApi } from '@/common/apis/approval' +import type { ApprovalGoodsCellEntity, ApprovalGoodsEntity, HandleApprovalAssetRequestData, HandleApprovalRequestData, ReturnApprovalDetailDTO } from '@/common/apis/approval/type' import { useRoute, useRouter } from 'vue-router' import { useApprovalStore } from '@/pinia/stores/approval' import { useWxStore } from '@/pinia/stores/wx'; +import { getApprovalDetailAssetApi } from '@/common/apis/approval'; import Compressor from 'compressorjs'; -import { useAb98UserStore } from '@/pinia/stores/ab98-user' -import { ShopOrderGoodsEntity } from '@/common/apis/shop/type' +import { useAb98UserStore } from '@/pinia/stores/ab98-user'; +import { ShopOrderGoodsEntity } from '@/common/apis/shop/type'; const { VITE_APP_BASE_API } = import.meta.env; const router = useRouter() @@ -20,6 +21,8 @@ const { openid, balance, corpidLogin, userid: qyUserid, name: qyName } = storeTo const ab98UserStore = useAb98UserStore(); const { tel, userid: ab98Userid, name } = storeToRefs(ab98UserStore); + +const detailData = ref<ReturnApprovalDetailDTO>(); const formData = ref<HandleApprovalAssetRequestData>({ approvalId: approvalStore.currentApproval?.approvalId || 0, status: 2, @@ -61,9 +64,9 @@ const validateForm = () => { showConfirmDialog({ title: '提示', message: '驳回时必须填写审核说明' }) return false } - + // 验证审批数量 - if (approvalStore.currentApproval?.status === 1) { + if (detailData.value?.status === 1) { for (const item of orderGoods.value) { if (item.approvalQuantity != null && item.approvalQuantity < 0) { showConfirmDialog({ title: '提示', message: `商品${item.goodsName}的审批数量不能为负数` }) @@ -104,51 +107,53 @@ const previewImage = (url: string) => { const approvalGoodsCells = ref<ApprovalGoodsCellEntity[]>([]); const approvalGoodsCellsWithNames = computed(() => { - return approvalGoodsCells.value.map(cell => { - const goods = orderGoods.value.find(g => g.approvalGoodsId === cell.approvalGoodsId); - return { - ...cell, - goodsName: goods ? goods.goodsName : '' - }; - }); + return approvalGoodsCells.value.map(cell => { + const goods = orderGoods.value.find(g => g.approvalGoodsId === cell.approvalGoodsId); + return { + ...cell, + goodsName: goods ? goods.goodsName : '' + }; + }); }); -onMounted(async () => { - if (!approvalStore.currentApproval) { +const fetchApprovalDetail = async () => { + const approvalId = approvalStore.currentApproval?.approvalId + if (!approvalId) { router.push('/approvalAsset/list'); return; } - // 初始化订单商品数据,添加approvalQuantity字段 - orderGoods.value = (approvalStore.currentApproval.goodsList || []).map(item => ({ - ...item, - approvalQuantity: approvalStore.currentApproval?.status === 1 ? item.applyQuantity : item.approvalQuantity - })); + try { + const result = await getApprovalDetailAssetApi(approvalId); + if (result.code === 0) { + 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) { - // 填充历史审批数据 - formData.value = { - ...formData.value, - corpid: wxStore.corpid, - status: approvalStore.currentApproval.status, - returnAmount: approvalStore.currentApproval.returnAmount, - auditRemark: approvalStore.currentApproval.auditRemark, - auditImages: approvalStore.currentApproval.auditImages - }; - - // 获取已审批商品格口信息 - try { - const result = await getApprovalGoodsCellApi(approvalStore.currentApproval.approvalId); - if (result.code === 0) { - approvalGoodsCells.value = result.data; - } else { - showDialog({ title: '错误', message: result.msg || '获取审批商品格口信息失败' }); + if (result.data.status !== 1) { + formData.value = { + ...formData.value, + corpid: wxStore.corpid, + status: result.data.status, + returnAmount: result.data.returnAmount, + auditRemark: result.data.auditRemark, + auditImages: result.data.auditImages + }; + approvalGoodsCells.value = result.data.approvalGoodsCellList || []; } - } catch (error) { - console.error('获取审批商品格口信息失败:', error); - showDialog({ title: '错误', message: '获取审批商品格口信息失败' }); + } else { + showDialog({ title: '错误', message: result.msg || '获取审批详情失败' }); } + } catch (error) { + console.error('获取审批详情失败:', error); + showDialog({ title: '错误', message: '获取审批详情失败' }); } +} + +onMounted(async () => { + await fetchApprovalDetail(); }) const handleOpenCell = async (approvalGoodsCellId: number) => { @@ -186,21 +191,6 @@ const handleOpenCell = async (approvalGoodsCellId: number) => { const handleSubmit = 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; @@ -239,6 +229,53 @@ const handleComfirm = () => { 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 = () => { formData.value.status = 3; handleSubmit(); @@ -252,9 +289,8 @@ const handleReject = () => { <div class="content-wrapper"> <van-cell-group> - <van-cell title="申请人" :value="approvalStore.currentApproval?.applyUserName" /> - <van-cell title="当前状态" :value="statusMap[approvalStore.currentApproval?.status || 1]" /> - <!-- <van-cell title="领用说明" :value="approvalStore.currentApproval?.applyRemark" /> --> + <van-cell title="申请人" :value="detailData?.applyUserName" /> + <van-cell title="当前状态" :value="statusMap[detailData?.status || 1]" /> </van-cell-group> <van-cell-group class="product-list"> @@ -277,26 +313,27 @@ const handleReject = () => { </span> </div> <!-- 审批数量输入框 --> - <div v-if="approvalStore.currentApproval?.status === 1" class="approval-quantity"> + <div v-if="detailData?.status === 1" class="approval-quantity"> <span class="label">审批数量:</span> - <van-stepper - v-model.number="item.approvalQuantity" - :min="0" - :max="item.applyQuantity" - integer - style="width: 180px;" - /> + <van-stepper v-model.number="item.approvalQuantity" :min="0" :max="item.applyQuantity" + integer style="width: 180px;" /> </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="value">{{ item.approvalQuantity }}</span> </div> </div> </van-cell> </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 class="approval-goods-list" v-if="approvalGoodsCells.length > 0"> <van-cell title="审批通过商品:" class="section-title" /> <template v-for="item in approvalGoodsCellsWithNames" :key="item.approvalGoodsCellId"> @@ -314,8 +351,9 @@ const handleReject = () => { <div class="van-ellipsis"> 分配数量:{{ item.allocateQuantity }} </div> - <div class="open-cell-btn"> - <van-button type="primary" size="small" @click="handleOpenCell(item.approvalGoodsCellId)" :disabled="isButtonDisabled"> + <div v-if="detailData?.status === 4" class="open-cell-btn"> + <van-button type="primary" size="small" + @click="handleOpenCell(item.approvalGoodsCellId)" :disabled="isButtonDisabled"> 打开格口 </van-button> </div> @@ -341,12 +379,13 @@ const handleReject = () => { </div> </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" style="flex: 1; height: 44px; border-radius: 8px; font-size: 16px;"> 拒绝 </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;"> 同意 </van-button> @@ -411,6 +450,7 @@ const handleReject = () => { .approval-quantity-view { justify-content: flex-end; } + .price-row { display: flex; justify-content: space-between; @@ -465,6 +505,23 @@ const handleReject = () => { 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 { padding-bottom: 100px; } @@ -490,4 +547,4 @@ const handleReject = () => { background-color: #ebedf0; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); } -</style> \ No newline at end of file +</style> diff --git a/src/pages/approvalAsset/list.vue b/src/pages/approvalAsset/list.vue index 55a5699..f893318 100644 --- a/src/pages/approvalAsset/list.vue +++ b/src/pages/approvalAsset/list.vue @@ -79,7 +79,8 @@ const statusOptions = [ const statusMap: { [key: number]: string } = { 1: '待审核', 2: '已通过', - 3: '已驳回' + 3: '已驳回', + 4: '开柜中' } const statusText = ref('')