From 292fc35d5414605787e8514e86597a016366f6b5 Mon Sep 17 00:00:00 2001 From: chenhao Date: Tue, 2 Dec 2025 14:04:23 +0800 Subject: [PATCH] =?UTF-8?q?feat(purchase):=20=E6=B7=BB=E5=8A=A0=E9=87=87?= =?UTF-8?q?=E8=B4=AD=E5=AE=A1=E6=89=B9=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增采购审批列表页面,支持待审批和已审批tab切换 - 实现采购详情页面,展示采购单信息、产品列表和审批历史 - 添加采购审批操作,支持通过和驳回两种审批状态 - 在首页添加采购审批菜单入口,与订单审批并列展示 - 路由调整,将原订单列表页路径改为首页路径 - 类型定义更新,增加采购相关接口和枚举类型 - 样式优化,统一采购审批页面的设计风格和交互体验 --- src/api/order.ts | 3 +- src/api/purchase.ts | 59 +++ src/main.ts | 2 + src/router/index.ts | 15 +- src/store/order.ts | 1 + src/store/purchase.ts | 255 +++++++++ src/types/index.ts | 55 +- src/views/Detail/index.vue | 17 +- src/views/Home/index.vue | 299 +++++++++++ src/views/List/index.vue | 111 +--- src/views/Purchase/index.vue | 458 +++++++++++++++++ src/views/PurchaseDetail/index.vue | 797 +++++++++++++++++++++++++++++ vite.config.ts | 1 + 概要设计文档.md | 382 +++++++++++++- 14 files changed, 2332 insertions(+), 123 deletions(-) create mode 100644 src/api/purchase.ts create mode 100644 src/store/purchase.ts create mode 100644 src/views/Home/index.vue create mode 100644 src/views/Purchase/index.vue create mode 100644 src/views/PurchaseDetail/index.vue diff --git a/src/api/order.ts b/src/api/order.ts index f51b903..73c31f1 100644 --- a/src/api/order.ts +++ b/src/api/order.ts @@ -78,6 +78,7 @@ export const getCompletedOrderList = (params: CompletedListParams): Promise>> => { + return http.get('/sip/purchaseorder/approveList', {params}) +} + +/** + * 获取采购已审批列表 + * + */ +export const getCompletedPurchaseList = (params: PurchaseListParams): Promise>> => { + // 创建FormData对象 + const formData = new FormData() + + // 添加参数到FormData + formData.append('page', params.page.toString()) + formData.append('pageSize', params.pageSize.toString()) + if (params.processKeyList) formData.append('processKeyList', params.processKeyList) + + return http.post('/flow/completed/list', formData) + +} + +/** + * 获取采购详情 + * + */ +export const getPurchaseDetail = (purchaseNo: string | number): Promise>> => { + return http.get(`/sip/purchaseorder/code/${purchaseNo}`) +} + +/** + * 提交采购审批结果 + */ +export const submitPurchaseApproval = (params: any): Promise>> => { + return http.post('/flow/todo/approve', params) +} + +/** + * 获取采购审批历史 + */ +export const getPurchaseApprovalHistory = (purchaseNo: string): Promise>> => { + let params = { + businessKey: purchaseNo || null, + processKeyList: ['purchase_order_online'], + } + return http.post('/flow/completed/all/list', params) +} diff --git a/src/main.ts b/src/main.ts index 8afecc5..6dc9991 100644 --- a/src/main.ts +++ b/src/main.ts @@ -5,6 +5,8 @@ import { store, initStores } from './store' // Vant样式 import 'vant/lib/index.css' +import 'vant/es/toast/style'; +import 'vant/es/style/base.css'; // 触摸模拟器 (开发环境使用) import '@vant/touch-emulator' diff --git a/src/router/index.ts b/src/router/index.ts index 90a1f5c..0bc3b30 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -19,10 +19,10 @@ const routes: RouteRecordRaw[] = [ }, { path: '/list', - name: 'OrderList', - component: () => import('@/views/List/index.vue'), + name: 'Home', + component: () => import('@/views/Home/index.vue'), meta: { - title: '订单列表', + title: '审批中心', requiresAuth: true } }, @@ -34,6 +34,15 @@ const routes: RouteRecordRaw[] = [ title: '订单详情', requiresAuth: true } + }, + { + path: '/purchase-detail/:id', + name: 'PurchaseDetail', + component: () => import('@/views/PurchaseDetail/index.vue'), + meta: { + title: '采购详情', + requiresAuth: true + } } ] diff --git a/src/store/order.ts b/src/store/order.ts index 5d821c9..b34712a 100644 --- a/src/store/order.ts +++ b/src/store/order.ts @@ -183,6 +183,7 @@ export const useOrderStore = defineStore('order', { const params: CompletedListParams = { page: this.completedCurrentPage, pageSize: this.completedPageSize, + processKeyList:['order_approve_online','order_approve_offline'], businessName: this.completedKeyword || undefined } diff --git a/src/store/purchase.ts b/src/store/purchase.ts new file mode 100644 index 0000000..cbca1b3 --- /dev/null +++ b/src/store/purchase.ts @@ -0,0 +1,255 @@ +import { defineStore } from 'pinia' +import type { Purchase, PurchaseListParams, PurchaseDetail } from '@/types' +import { getPurchaseList, getCompletedPurchaseList, getPurchaseDetail } from '@/api/purchase' + +interface PurchaseState { + // 待审批列表相关 + purchaseList: Purchase[] + loading: boolean + finished: boolean + currentPage: number + pageSize: number + total: number + keyword: string + + // 已审批列表相关 + completedList: any[] + completedLoading: boolean + completedFinished: boolean + completedCurrentPage: number + completedPageSize: number + completedTotal: number + completedKeyword: string + + // 详情相关 + currentPurchase: PurchaseDetail | null + currentPurchaseTodo: any | null // 待审批的todo信息(包含processKey, taskId等) + detailLoading: boolean +} + +export const usePurchaseStore = defineStore('purchase', { + state: (): PurchaseState => ({ + // 待审批列表状态 + purchaseList: [], + loading: false, + finished: false, + currentPage: 1, + pageSize: 20, + total: 0, + keyword: '', + + // 已审批列表状态 + completedList: [], + completedLoading: false, + completedFinished: false, + completedCurrentPage: 1, + completedPageSize: 20, + completedTotal: 0, + completedKeyword: '', + + // 详情相关 + currentPurchase: null, + currentPurchaseTodo: null, + detailLoading: false + }), + + getters: { + // 获取采购产品列表 + purchaseItems: (state) => state.currentPurchase?.omsPurchaseOrderItemList || [], + + // 检查待审批是否还有更多数据 + hasMore: (state) => state.purchaseList.length < state.total, + + // 检查已审批是否还有更多数据 + completedHasMore: (state) => state.completedList.length < state.completedTotal + }, + + actions: { + /** + * 加载采购待审批列表 + */ + async loadPurchaseList(refresh = false) { + if (this.loading) return + + if (refresh) { + this.currentPage = 1 + this.finished = false + this.purchaseList = [] + } + + this.loading = true + + try { + const params: PurchaseListParams = { + page: this.currentPage, + pageSize: this.pageSize, + keyword: this.keyword || undefined + } + + const response = await getPurchaseList(params) + const data = response.data + const total = data.total || 0 + const rows = data.rows || [] + + if (refresh) { + this.purchaseList = rows + } else { + this.purchaseList.push(...rows) + } + + this.total = total + + // 判断是否已加载完所有数据 + if (this.purchaseList.length >= total || rows.length === 0) { + this.finished = true + } else { + // 只有当还有更多数据时才递增页码 + this.currentPage++ + } + + return response + } catch (error) { + console.error('加载采购列表失败:', error) + throw error + } finally { + this.loading = false + } + }, + + /** + * 搜索采购 + */ + async searchPurchases(keyword: string) { + this.keyword = keyword + await this.loadPurchaseList(true) + }, + + /** + * 加载已审批列表 + */ + async loadCompletedPurchaseList(refresh = false) { + // 如果已经加载完所有数据且不是刷新操作,直接返回 + if (this.completedFinished && !refresh) { + return Promise.resolve() + } + + if (refresh) { + this.completedCurrentPage = 1 + this.completedFinished = false + this.completedList = [] + } + + this.completedLoading = true + + try { + const params: PurchaseListParams = { + page: this.completedCurrentPage, + pageSize: this.completedPageSize, + keyword: this.completedKeyword || undefined, + processKeyList:['purchase_order_online'] + } + + const response = await getCompletedPurchaseList(params) + const data = response.data + const total = data.total || 0 + const rows = data.rows || [] + + if (refresh) { + this.completedList = rows + } else { + this.completedList.push(...rows) + } + + this.completedTotal = total + + // 判断是否已加载完所有数据 + if (this.completedList.length >= total || rows.length === 0) { + this.completedFinished = true + } else { + // 只有当还有更多数据时才递增页码 + this.completedCurrentPage++ + } + + return response + } catch (error) { + console.error('加载已审批采购列表失败:', error) + throw error + } finally { + this.completedLoading = false + } + }, + + /** + * 搜索已审批采购 + */ + async searchCompletedPurchases(keyword: string) { + this.completedKeyword = keyword + await this.loadCompletedPurchaseList(true) + }, + + /** + * 重置列表状态 + */ + resetListState() { + this.purchaseList = [] + this.currentPage = 1 + this.finished = false + this.loading = false + this.keyword = '' + this.total = 0 + }, + + /** + * 重置已审批列表状态 + */ + resetCompletedListState() { + this.completedList = [] + this.completedCurrentPage = 1 + this.completedFinished = false + this.completedLoading = false + this.completedKeyword = '' + this.completedTotal = 0 + }, + + /** + * 获取采购详情 + */ + async fetchPurchaseDetail(purchaseNo: string | number) { + this.detailLoading = true + + try { + const response = await getPurchaseDetail(purchaseNo) + + // 直接获取数据对象 + const purchaseData = response.data + + // 确保数据存在再赋值 + if (purchaseData) { + this.currentPurchase = purchaseData.data + } + + return response + } catch (error) { + console.error('获取采购详情失败:', error) + throw error + } finally { + this.detailLoading = false + } + }, + + /** + * 设置当前采购单的todo信息 + */ + setCurrentPurchaseTodo(todoInfo: any) { + this.currentPurchaseTodo = todoInfo + }, + + /** + * 清空当前采购详情 + */ + clearCurrentPurchase() { + this.currentPurchase = null + this.currentPurchaseTodo = null + } + } +}) diff --git a/src/types/index.ts b/src/types/index.ts index d4a2924..198113e 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -2,7 +2,7 @@ export interface ApiResponse { code: number msg: string | null - data: T + rows: any[T] total?: number } @@ -20,6 +20,7 @@ export type PayMethod = '1-1' | '1-2' | '2-1' | '2-2' | '2-3' // 待审批、已 // 审批状态类型 export type ApprovalStatus = 1 | 2 | 3 // 待审批、驳回、通过 +export type ApproveBtn = 0 | 1 // 驳回、通过 // 订单信息类型 export interface Order { @@ -238,4 +239,56 @@ export interface CompletedListParams { businessName?: string page: number pageSize: number + processKeyList: Array +} + +// ============= 采购相关类型定义 ============= + +// 采购订单信息类型 +export interface Purchase { + id: number + purchaseNo: string // 采购单号 + approveStatus: string // 审批状态 + vendorName: string // 制造商名称 + ownerName: string // 汇智负责人 + totalAmount: number // 采购金额 + createTime: string + updateTime: string + + [key: string]: any +} + +// 采购列表查询参数 +export interface PurchaseListParams { + page: number + pageSize: number + keyword?: string + processKeyList?: string[] +} + +// 采购产品项类型 +export interface PurchaseOrderItem { + id: number + productCode: string // 产品编码 + productModel: string // 产品型号 + productDescription: string // 描述 + quantity: number // 数量 + price: number // 价格 + [key: string]: any +} + +// 采购详情类型 +export interface PurchaseDetail { + id: number + purchaseNo: string // 采购单号 + createTime: string // 发起日期 + purchaserName: string // 采购员 + purchaserMobile: string // 联系电话 + purchaserEmail: string // 联系邮箱 + warehouseName: string // 入库仓 + payMethod: string // 付款方式 + ownerName: string // 汇智负责人 + remark: string // 备注 + omsPurchaseOrderItemList: PurchaseOrderItem[] // 采购产品列表 + [key: string]: any } \ No newline at end of file diff --git a/src/views/Detail/index.vue b/src/views/Detail/index.vue index f3123b0..1599307 100644 --- a/src/views/Detail/index.vue +++ b/src/views/Detail/index.vue @@ -649,7 +649,16 @@ const getFinalTotalAmount = () => { // 返回上一页 const goBack = () => { - router.back() + const from = route.query.from as string; + if (from) { + router.push(`/?tab=${from}`); + } else { + if (window.history.length > 1) { + router.back(); + } else { + router.push('/'); + } + } } // 预览文件 @@ -812,10 +821,10 @@ const submitApproval = async () => { showSuccessToast(currentApprovalStatus.value === 0 ? '驳回成功' : '审批通过') approvalDialogVisible.value = false - // 如果是审批通过,跳转到列表页面 + // 如果是审批通过,跳转到订单列表页面 if (currentApprovalStatus.value !== 0) { - // 跳转到列表页面 - router.push('/list') + // 跳转到订单列表页面 + router.push('/list?tab=order') } else { // 驳回情况下重新加载详情 await orderStore.fetchOrderDetail(route.params.id as string) diff --git a/src/views/Home/index.vue b/src/views/Home/index.vue new file mode 100644 index 0000000..a9269ec --- /dev/null +++ b/src/views/Home/index.vue @@ -0,0 +1,299 @@ + + + + + diff --git a/src/views/List/index.vue b/src/views/List/index.vue index 1cf3d7f..a36a656 100644 --- a/src/views/List/index.vue +++ b/src/views/List/index.vue @@ -1,23 +1,5 @@