From 15c24624b0770e6ff4f9dc5fe600a5318f9f92ad Mon Sep 17 00:00:00 2001 From: chenhao Date: Tue, 6 Jan 2026 18:02:44 +0800 Subject: [PATCH] =?UTF-8?q?feat(finance):=20=E6=B7=BB=E5=8A=A0=E5=BA=94?= =?UTF-8?q?=E4=BB=98=E5=AE=A1=E6=89=B9=E5=8A=9F=E8=83=BD=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增应付详情页面,支持查看付款信息和应付单列表 - 实现应付审批流程,包含通过和驳回功能 - 添加应付列表页面,支持待审批和已审批分类查看 - 集成审批意见标签功能,提供常用审批意见选择 - 扩展 finance store 状态管理,添加应付相关数据处理 - 添加应付审批相关路由配置和类型定义 - 在首页添加应付审批入口和统计数据展示 --- src/router/index.ts | 9 + src/store/finance.ts | 158 +++ src/types/index.ts | 40 + src/views/Home/index.vue | 12 +- src/views/finance/payable/detail.vue | 437 ++++++ src/views/finance/payable/index.vue | 234 ++++ 概要设计文档.md | 1929 +++----------------------- 7 files changed, 1075 insertions(+), 1744 deletions(-) create mode 100644 src/store/finance.ts create mode 100644 src/views/finance/payable/detail.vue create mode 100644 src/views/finance/payable/index.vue diff --git a/src/router/index.ts b/src/router/index.ts index 0bc3b30..10417ab 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -43,6 +43,15 @@ const routes: RouteRecordRaw[] = [ title: '采购详情', requiresAuth: true } + }, + { + path: '/finance/payable/detail/:paymentBillCode', + name: 'FinancePayableDetail', + component: () => import('@/views/finance/payable/detail.vue'), + meta: { + title: '应付详情', + requiresAuth: true + } } ] diff --git a/src/store/finance.ts b/src/store/finance.ts new file mode 100644 index 0000000..f3766f5 --- /dev/null +++ b/src/store/finance.ts @@ -0,0 +1,158 @@ +import { defineStore } from 'pinia' +import { ref } from 'vue' +import { getPayableList } from '@/api/finance' // borrowing completed from finance api if I add it, or use generic +// Actually I didn't add getCompleted to finance.ts, I should probably add it or use the one from purchase/order? +// Better to add a generic one or specific one in finance.ts +// Let's modify api/finance.ts to include getCompletedPayableList which calls /flow/completed/list +import type { FinancePayable } from '@/types' + +// Re-importing getCompletedPurchaseList is wrong if it's not there. +// I will just use the same pattern as PurchaseStore. +import http from '@/utils/http' // Direct call if needed or add to api + +export const useFinanceStore = defineStore('finance', () => { + // State + const payableList = ref([]) + const loading = ref(false) + const finished = ref(false) + const page = ref(1) + const pageSize = ref(10) + const total = ref(0) + + // Completed State + const completedList = ref([]) + const completedLoading = ref(false) + const completedFinished = ref(false) + const completedPage = ref(1) + const completedPageSize = ref(10) + + // Detail State + const currentPayable = ref({}) + const currentPayableTodo = ref(null) + const detailLoading = ref(false) + + // Actions + const loadPayableList = async (refresh = false) => { + if (refresh) { + page.value = 1 + finished.value = false + payableList.value = [] + } + + loading.value = true + try { + const res = await getPayableList({ + pageNum: page.value, + pageSize: pageSize.value, + processKey: 'finance_payment' + }) + + if (res.data.code === 0) { + const rows = res.data.rows || [] + + if (refresh) { + payableList.value = rows + } else { + payableList.value = [...payableList.value, ...rows] + } + + total.value = res.data.total || 0 + if (payableList.value.length >= total.value || rows.length < pageSize.value) { + finished.value = true + } else { + page.value++ + } + } + } catch (error) { + console.error('Failed to load payable list', error) + finished.value = true + } finally { + loading.value = false + } + } + + const loadCompletedList = async (refresh = false) => { + if (refresh) { + completedPage.value = 1 + completedFinished.value = false + completedList.value = [] + } + + completedLoading.value = true + try { + const formData = new FormData() + formData.append('page', completedPage.value.toString()) + formData.append('pageSize', completedPageSize.value.toString()) + formData.append('processKeyList', 'finance_payment') + + const res = await http.post('/flow/completed/list', formData) + + if (res.data.code === 0) { + const rows = res.data.rows || [] + if (refresh) { + completedList.value = rows + } else { + completedList.value = [...completedList.value, ...rows] + } + + if (rows.length < completedPageSize.value) { + completedFinished.value = true + } else { + completedPage.value++ + } + } + } catch (error) { + console.error('Failed to load completed list', error) + completedFinished.value = true + } finally { + completedLoading.value = false + } + } + + const fetchPayableDetail = async (id: string | number) => { + detailLoading.value = true + try { + // Import getPayableDetail dynamically to avoid circular dependency if any? No, it's fine. + // But I need to import it at the top. + const { getPayableDetail } = await import('@/api/finance') + const res = await getPayableDetail(id) + if (res.data.code === 0) { + currentPayable.value = res.data.data || res.data.rows || {} // handle structure + // Attempt to extract todo info from response if available, similar to Purchase/Order + // If not available in detail, we might need to rely on list passing it or separate call. + // For now, assume it's in the detail or passed via other means. + // If the detail response has 'todo' field: + if (res.data.data?.todo) { + currentPayableTodo.value = res.data.data.todo + } + } + } catch (error) { + console.error('Failed to load payable detail', error) + } finally { + detailLoading.value = false + } + } + + const resetState = () => { + page.value = 1 + payableList.value = [] + finished.value = false + loading.value = false + } + + return { + payableList, + loading, + finished, + loadPayableList, + completedList, + completedLoading, + completedFinished, + loadCompletedList, + currentPayable, + currentPayableTodo, + detailLoading, + fetchPayableDetail, + resetState + } +}) diff --git a/src/types/index.ts b/src/types/index.ts index 3bca843..abb9944 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -302,4 +302,44 @@ export interface PurchaseDetail { attachmentList?: AttachmentFile[] // 其他附件列表 fileLog?: AttachmentFile // 单个附件 [key: string]: any +} + +// ============= 应付审批相关类型定义 ============= + +export interface PayableDetailItem { + payableBillCode: string + projectName: string + productType: string + totalPriceWithTax: number + paymentAmount: number + [key: string]: any +} + +export interface FinancePayable { + paymentBillCode: string // 付款单编号 (was businessKey) + vendorName: string // 制造商名称 + totalPriceWithTax: number // 含税总价 + applyTime: string // 申请时间 + + // Detail fields + payType?: string // 付款条件 + payConfigDay?: number // 付款周期 + totalPriceWithoutTax?: number // 未税总价 + taxAmount?: number // 税额 + paymentMethod?: string // 支付方式 + payBankNumber?: string // 银行账号 + payName?: string // 账户名称 + payBankOpenAddress?: string // 银行开户行 + bankNumber?: string // 银行行号 + + payableDetails?: PayableDetailItem[] // 应付单列表 + + [key: string]: any +} + +export interface FinancePayableListParams { + pageNum: number + pageSize: number + processKey: string + [key: string]: any } \ No newline at end of file diff --git a/src/views/Home/index.vue b/src/views/Home/index.vue index 8d33c5c..ea59cb5 100644 --- a/src/views/Home/index.vue +++ b/src/views/Home/index.vue @@ -58,6 +58,9 @@ + + + @@ -71,6 +74,7 @@ import { useTodoStore } from '@/store/todo' import { storeToRefs } from 'pinia' import OrderList from '@/views/List/index.vue' import PurchaseList from '@/views/Purchase/index.vue' +import FinancePayableList from '@/views/finance/payable/index.vue' const router = useRouter() const route = useRoute() @@ -97,6 +101,12 @@ const menuList = computed(() => [ title: '采购审批', icon: 'shopping-cart-o', count: statistics.value?.purchase_order_online || 0 + }, + { + key: 'finance_payment', + title: '应付审批', + icon: 'gold-coin-o', + count: statistics.value?.finance_payment || 0 } ]) @@ -116,7 +126,7 @@ const selectMenu = (key: string) => { onMounted(() => { todoStore.fetchTodoStatistics() const tab = route.query.tab as string - if (tab && ['order', 'purchase'].includes(tab)) { + if (tab && ['order', 'purchase', 'finance_payment'].includes(tab)) { currentMenu.value = tab } }) diff --git a/src/views/finance/payable/detail.vue b/src/views/finance/payable/detail.vue new file mode 100644 index 0000000..d51139e --- /dev/null +++ b/src/views/finance/payable/detail.vue @@ -0,0 +1,437 @@ + + + + + \ No newline at end of file diff --git a/src/views/finance/payable/index.vue b/src/views/finance/payable/index.vue new file mode 100644 index 0000000..07440f4 --- /dev/null +++ b/src/views/finance/payable/index.vue @@ -0,0 +1,234 @@ + + + + + diff --git a/概要设计文档.md b/概要设计文档.md index 0533703..b085f56 100644 --- a/概要设计文档.md +++ b/概要设计文档.md @@ -14,36 +14,44 @@ ## 2. 技术架构 ### 2.1 技术栈选择 -- **前端框架**: Vue 3 + TypeScript -- **构建工具**: Vite -- **UI组件库**: Vant 4 (专为移动端设计) -- **HTTP客户端**: Axios -- **路由管理**: Vue Router 4 -- **状态管理**: Pinia -- **样式预处理器**: SCSS +- **前端框架**: Vue 3.3.4 + TypeScript +- **构建工具**: Vite 4.4.9 +- **UI组件库**: Vant 4.6.6 (专为移动端设计) +- **HTTP客户端**: Axios 1.5.0 +- **路由管理**: Vue Router 4.2.4 +- **状态管理**: Pinia 2.1.6 +- **样式预处理器**: SCSS (Sass) +- **PDF预览**: vue-pdf-embed + pdfjs-dist ### 2.2 项目结构 ``` -oms_h5/ +oms_vue/ ├── public/ -│ └── index.html ├── src/ │ ├── api/ # API接口管理 +│ │ ├── auth.ts # 认证接口 │ │ ├── order.ts # 订单相关接口 -│ │ └── purchase.ts # 采购相关接口 -│ ├── components/ # 公共组件 -│ ├── views/ # 页面组件 -│ │ ├── Home/ # 主页面(审批中心) -│ │ ├── List/ # 订单审批列表页面 -│ │ ├── Purchase/ # 采购审批列表页面 -│ │ ├── Detail/ # 订单详情页面 -│ │ └── PurchaseDetail/ # 采购详情页面 -│ ├── store/ # 状态管理 -│ │ ├── order.ts # 订单状态管理 -│ │ └── purchase.ts # 采购状态管理 -│ ├── utils/ # 工具函数 -│ ├── types/ # TypeScript类型定义 -│ └── styles/ # 全局样式 +│ │ ├── purchase.ts # 采购相关接口 +│ │ └── todo.ts # 待办相关接口 +│ ├── router/ # 路由配置 +│ ├── store/ # 状态管理 +│ │ ├── auth.ts # 认证状态 +│ │ ├── order.ts # 订单状态 +│ │ └── purchase.ts # 采购状态 +│ ├── styles/ # 全局样式 +│ ├── types/ # TypeScript类型定义 +│ ├── utils/ # 工具函数 (http封装等) +│ ├── views/ # 页面组件 +│ │ ├── Home/ # 审批中心主页 (含抽屉菜单) +│ │ ├── List/ # 订单审批列表组件 +│ │ ├── Purchase/ # 采购审批列表组件 +│ │ ├── Detail/ # 订单详情页面 +│ │ ├── PurchaseDetail/# 采购详情页面 +│ │ └── Login/ # 登录页面 +│ ├── App.vue +│ └── main.ts +├── .env.development # 开发环境配置 +├── .env.production # 生产环境配置 ├── package.json └── vite.config.ts ``` @@ -51,1779 +59,214 @@ oms_h5/ ## 3. 功能模块设计 ### 3.0 主页面模块(审批中心) -**功能描述**: 提供左侧抽屉菜单导航,统一管理不同类型的审批入口 +**功能描述**: 提供左侧抽屉菜单导航,统一管理不同类型的审批入口。 + +**组件位置**: `src/views/Home/index.vue` **页面架构**: -- **顶部导航栏**: 显示当前菜单标题、菜单图标和退出按钮 -- **左侧抽屉菜单**: 展示所有审批类型的菜单项 -- **内容区域**: 根据选中的菜单项动态显示对应的审批列表 +- **顶部导航栏**: 显示当前菜单标题、菜单图标和退出按钮。 +- **左侧抽屉菜单**: 展示所有审批类型的菜单项(订单审批、采购审批)。 +- **内容区域**: 根据选中的菜单项动态切换显示 `List` (订单列表) 或 `Purchase` (采购列表) 组件。 **主要功能**: -- 左侧抽屉菜单切换不同审批类型 -- 菜单项包含图标、标题和激活状态显示 -- 统一的退出登录功能 -- 响应式菜单宽度(占屏幕70%) +- 抽屉式菜单切换审批类型。 +- 统一的退出登录功能。 +- 动态组件 (``) 切换列表视图。 -**菜单项列表**: -1. **订单审批** (icon: notes-o) - - 展示订单审批的待审批和已审批列表 - - 支持订单详情查看和审批操作 -2. **采购审批** (icon: shopping-cart-o) - - 展示采购审批的待审批和已审批列表 - - 支持采购详情查看和审批操作 - -**交互行为**: -- 点击左上角菜单图标打开抽屉 -- 点击菜单项切换审批类型并关闭抽屉 -- 当前选中的菜单项高亮显示 -- 支持点击遮罩层或关闭图标关闭抽屉 - -**路由配置**: -```typescript -{ - path: '/list', - name: 'Home', - component: () => import('@/views/Home/index.vue'), - meta: { - title: '审批中心', - requiresAuth: true - } -} -``` +**菜单配置**: +1. **订单审批** (icon: notes-o) -> 对应 `List` 组件 +2. **采购审批** (icon: shopping-cart-o) -> 对应 `Purchase` 组件 ### 3.1 订单审批列表模块 -**功能描述**: 采用双Tab设计,支持查看待审批和已审批两种状态的订单列表 - -**页面架构**: -- **Tab1 - 待审批**: 展示当前用户需要审批的订单列表 -- **Tab2 - 已审批**: 展示用户已完成审批的历史记录 - -**主要功能**: -- 双Tab切换界面,独立状态管理 -- 支持关键词搜索(待审批:订单编号、客户名称;已审批:合同名称) -- 无限滚动分页加载 -- 下拉刷新功能 -- 点击跳转详情页(已审批为只读模式) +**功能描述**: 采用双Tab设计,支持查看待审批和已审批两种状态的订单列表。 **组件位置**: `src/views/List/index.vue` -**设计说明**: -- 该组件作为子组件嵌入到Home主页面中 -- 移除了独立的顶部导航栏和退出按钮 -- 保持原有的搜索、列表展示和审批功能 +**Tab设计**: +- **Tab1 - 待审批**: 展示用户需要审批的订单。支持按"订单编号"、"客户名称"搜索。 +- **Tab2 - 已审批**: 展示用户已审批的历史记录。支持按"合同名称"搜索。 -#### 3.1.1 待审批Tab +**数据展示**: +- **待审批**: 订单编号、项目名称、客户名称、订单金额、创建时间。 +- **已审批**: 合同编号、合同名称、流程名称、发起人、审批时间、审批状态、审批意见。 -**数据展示字段**: -- 订单编号(orderCode) -- 项目名称(projectName) -- 客户名称(customerName) -- 订单金额(shipmentAmount) -- 创建时间(createTime) -- 订单状态(固定显示"待审批") +**接口定义**: +- **待审批列表**: `POST /project/order/list` +- **已审批列表**: `POST /flow/completed/list` -**交互行为**: -- 搜索框支持订单编号、客户名称搜索 -- 列表项点击跳转详情页(可审批操作) -- 上拉加载更多,下拉刷新 +### 3.2 订单详情页面模块 +**功能描述**: 展示订单详细信息、附件、审批历史,并提供审批操作。 -#### 3.1.2 已审批Tab - -**数据展示字段**: -- 合同编号(businessKey) -- 合同名称(businessName) -- 流程名称(processName) -- 发起人(applyUserName) -- 审批时间(approveTime) -- 审批状态(approveStatus: 2-驳回,3-通过,其他-提交) -- 审批意见(approveOpinion) - -**交互行为**: -- 搜索框支持合同名称搜索 -- 列表项点击跳转详情页(只读模式,无审批按钮) -- Tab切换时自动清空搜索关键词 -- 上拉加载更多,下拉刷新 - -**接口需求**: -```typescript -// 获取待审批订单列表 -POST /project/order/list -参数: { - approve: "approve", - page: number, - pageSize: number, - keyword?: string -} - -// 获取已审批列表 -POST /flow/completed/list -参数: { - page: number, - pageSize: number, - businessName?: string -} -响应结果示例:{ - "total": 1, - "rows": [ - { - "createBy": "1", - "createTime": "2025-05-30", - "updateBy": "1", - "updateTime": "2025-08-25 16:52:35", - "remark": "", - "id": 92, - "projectId": 92, - "projectCode": "V004592", - "projectName": "黑龙江省佳木斯附属第一医院2点胖终端云桌面项目", - "versionCode": "2", - "industryType": "zf", - "bgProperty": "SY", - "province": "黑龙江省", - "orderCode": "ZGXS-20250530HLJ001-VDI", - "customerName": "佳木斯大学附属第一医院", - "customerCode": "CU-HLJ-0002", - "customerPhone": "13352549898", - "customerUserName": "刘芸芸1111", - "shipmentAmount": 754169.99, - "orderStatus": "1", - "duty": "1", - "dutyName": "SIP管理员", - "agentName": "北京", - "agentCode": "BJS", - "notifier": "", - "city": "", - "businessPerson": "严浩", - "businessEmail": "", - "deleteFileId": null, - "businessPhone": "13512345457", - "currencyType": "rmb", - "partnerCode": "AGT-HLJ-0001", - "partnerName": "哈尔滨惠普天地电子有限公司", - "projectPartnerName": "哈尔滨惠普天地电子有限公司", - "productCodeList": null, - "actualPurchaseAmount": 777314.52, - "deliveryTime": "2025-06-04", - "deliveryTimeStart": null, - "deliveryTimeEnd": null, - "estimatedOrderTime": "2025-05-30", - "estimatedOrderTimeStart": null, - "estimatedOrderTimeEnd": null, - "orderEndTime": "2025-08-23", - "orderEndTimeStart": null, - "orderEndTimeEnd": null, - "updateTimeStart": null, - "updateTimeEnd": null, - "productSn": null, - "companyDelivery": "", - "notifierEmail": "", - "notifierPhone": "232", - "notifierAddress": "江西省南昌市高新区艾溪湖北路88号恒大中心A座1209室", - "dutyEmail": "mula.liu@163.com", - "dutyPhone": "18980500203", - "orderChannel": "1", - "partnerEmail": "", - "partnerUserName": "张树志", - "partnerPhone": "13936302299", - "systemUserId": "101", - "level": "02", - "processType": "0", - "processTemplate": "0", - "deliveryStatus": "1", - "signStatus": "0", - "outerStatus": "2", - "approveTime": "2025-08-19 16:46:26", - "approveTimeStart": null, - "approveTimeEnd": null, - "discountFold": 0.985, - "supplier": "紫光汇智信息技术有限公司", - "approve": null, - "contractFileList": null, - "configFileList": null, - "contractTableData": null, - "softwareProjectProductInfoList": null, - "hardwareProjectProductInfoList": null, - "maintenanceProjectProductInfoList": null - } - ], - "code": 0, - "msg": null -} -``` - -### 3.1.5 采购审批列表模块 -**功能描述**: 采用双Tab设计,支持查看待审批和已审批两种状态的采购单列表 - -**页面架构**: -- **Tab1 - 待审批**: 展示当前用户需要审批的采购单列表 -- **Tab2 - 已审批**: 展示用户已完成审批的采购历史记录 +**组件位置**: `src/views/Detail/index.vue` +**路由**: `/detail/:id` **主要功能**: -- 双Tab切换界面,独立状态管理 -- 支持关键词搜索(待审批:采购单号;已审批:采购合同名称) -- 无限滚动分页加载 -- 下拉刷新功能 -- 点击跳转详情页(已审批为只读模式) +- **项目/订单信息**: 客户信息、金额、相关人员等。 +- **产品明细**: 软件、硬件、维保产品列表。 +- **附件查看**: 合同附件、配置附件等。 +- **审批历史**: 展示审批流转记录。 +- **审批操作**: 通过、驳回、填写意见。 + +**接口定义**: +- **获取详情**: `GET /project/order/h5/approve/{id}` +- **提交审批**: `POST /project/order/order/approve` + +### 3.3 采购审批列表模块 +**功能描述**: 采用双Tab设计,支持查看待审批和已审批的采购单。 **组件位置**: `src/views/Purchase/index.vue` -**设计说明**: -- 该组件作为子组件嵌入到Home主页面中 -- UI结构和交互逻辑参照订单审批列表模块 -- 接口调用部分预留TODO标记,待后续对接 +**Tab设计**: +- **Tab1 - 待审批**: 展示待审批采购单。支持按"采购单号"搜索。 +- **Tab2 - 已审批**: 展示已审批采购记录。支持按"合同名称"搜索。 -**待审批Tab数据展示字段**: -- 采购单号(purchaseNo) -- 审批状态(approveStatus) -- 制造商名称(vendorName) -- 汇智负责人(ownerName) -- 采购金额(totalAmount) -- 创建时间(createTime) +**接口定义**: +- **待审批列表**: `GET /sip/purchaseorder/approveList` +- **已审批列表**: `POST /flow/completed/list` (参数 `processKeyList` 包含 `purchase_order_online` 等) -**已审批Tab数据展示字段**: -- 合同编号(businessKey) -- 合同名称(businessName) -- 流程名称(processName) -- 发起人(applyUserName) -- 审批时间(approveTime) -- 审批状态(approveStatus: 2-驳回,3-通过,其他-提交) -- 审批意见(approveOpinion) - -**接口需求**: -```typescript -// 获取待审批采购列表 -GET /sip/purchaseorder/approveList -参数: { - page: number, - pageSize: number, - keyword?: string -} - -响应结果示例:{ - "code": 0, - "msg": "操作成功", - "data": { - "total": 100, - "rows": [ - { - "id": 1, - "purchaseNo": "PO20251201001", - "approveStatus": "待审批", - "vendorName": "XX制造商", - "ownerName": "张三", - "totalAmount": 100000.00, - "createTime": "2025-12-01 10:00:00" - } - ] - } -} - -// 待实现:获取已审批采购列表 -GET /sip/purchaseorder/completedList -参数: { - page: number, - pageSize: number, - keyword?: string -} -``` - -**路由配置**: -```typescript -// 采购详情页面路由 -{ - path: '/purchase-detail/:id', - name: 'PurchaseDetail', - component: () => import('@/views/PurchaseDetail/index.vue'), - meta: { - title: '采购详情', - requiresAuth: true - } -} -``` - -### 3.1.6 采购详情页面模块 -**功能描述**: 展示采购单详细信息,包括订单信息和采购产品列表 - -**页面架构**: -- **Tab1 - 订单信息**: 展示采购单的基本信息 -- **Tab2 - 采购列表**: 展示采购的产品明细 - -**主要功能**: -- 采购单基本信息展示 -- 采购产品列表展示 -- 产品总金额计算 +### 3.4 采购详情页面模块 +**功能描述**: 展示采购单详细信息和产品列表,支持审批操作。 **组件位置**: `src/views/PurchaseDetail/index.vue` +**路由**: `/purchase-detail/:id` (id为采购单号 purchaseNo) -**订单信息Tab展示字段**: -- 采购单号(purchaseNo) -- 发起日期(createTime) -- 采购员(purchaserName) -- 联系电话(purchaserMobile) -- 联系邮箱(purchaserEmail) -- 入库仓(warehouseName) -- 付款方式(payMethodDesc) -- 汇智负责人(ownerName) -- 备注(remark) +**页面架构**: +- **Tab1 - 订单信息**: 采购单号、供应商、金额、付款方式、仓库等基本信息。 +- **Tab2 - 采购列表**: 采购产品明细(型号、描述、数量、单价、小计)。 +- **底部操作栏**: 审批通过/驳回按钮。 -**采购列表Tab展示字段**: -数据来源:`omsPurchaseOrderItemList` 数组 -- 产品编码(productCode) -- 产品型号(productModel) -- 描述(productDescription) -- 数量(quantity) -- 单价(price) -- 小计(自动计算:price × quantity) -- 总金额(所有产品小计之和) +**接口定义**: +- **获取详情**: `GET /sip/purchaseorder/code/{purchaseNo}` +- **提交审批**: `POST /flow/todo/approve` +- **审批历史**: `POST /flow/completed/all/list` -**接口需求**: -```typescript -// 获取采购详情 -GET /sip/purchaseorder/code/{purchaseNo} +## 4. 数据接口规范 -响应结果示例:{ - "code": 0, - "msg": "操作成功", - "data": { - "id": 1, - "purchaseNo": "PO20251201001", - "createTime": "2025-12-01 10:00:00", - "purchaserName": "张三", - "purchaserMobile": "13800138000", - "purchaserEmail": "zhangsan@example.com", - "warehouseName": "北京仓库", - "payMethodDesc": "货到付款", - "ownerName": "李四", - "remark": "紧急采购", - "omsPurchaseOrderItemList": [ - { - "id": 1, - "productCode": "P001", - "productModel": "Model-A", - "productDescription": "产品描述信息", - "quantity": 10, - "price": 100.00 - } - ] - } -} -``` - -### 3.2 详情页面模块 -**功能描述**: 展示工单详细信息和审批操作 - -**主要功能**: -- 工单详情信息展示 -- 审批历史记录 -- 附件预览(图片、文档) -- 审批操作按钮 - -**接口需求**: -```typescript -//获取已审批列表 -POST /flow/completed/list -响应结果示例:{ - "code": 0, - "msg": null, - "rows": [ - { - "allApproveUserName": "chenhao", - "applyTime": "2025-09-19 17:06", - "applyUserName": "chenhao", - "approveOpinion": "经审查无误,予以批准", - "approveStatus": 3, - "approveTime": "2025-09-19 17:07", - "approveUser": "101", - "approveUserName": "chenhao", - "businessId": 257, - "businessKey": "ZGXV-20250919BJS001", - "businessName": "测试-重庆xx学校云桌面项目", - "createBy": null, - "createTime": null, - "extendField1": "1", - "extendField2": null, - "formKey": null, - "id": null, - "nextAllApproveUserName": "chenhao", - "processInstanceId": "58ce6889-9536-11f0-8f98-00ff08deec4d", - "processKey": "order_approve_online", - "processName": "订单审批流程", - "recoveryType": null, - "remark": null, - "roleName": "商务,鼎盛", - "taskId": "fb6c16dd-9537-11f0-8f98-00ff08deec4d", - "taskName": "领导1", - "taxRateData": null, - "todoId": "1968965000342323200", - "updateBy": null, - "updateTime": null, - "variables": null - } - ]} -//获取工单详情 -GET /project/order/h5/approve/:id -响应结果示例:{ - "msg": "操作成功", - "code": 0, - "data": { - "todo": null, - "approveLog": [ - { - "createBy": null, - "createTime": null, - "updateBy": null, - "updateTime": null, - "remark": null, - "id": null, - "todoId": "1959901714317623296", - "businessKey": "ZGXS-20250530HLJ001-VDI", - "processKey": "order_approve_online", - "processName": "订单审批流程", - "taskName": "售前", - "approveUserName": "SIP管理员", - "allApproveUserName": "SIP管理员", - "nextAllApproveUserName": "yeyuhao", - "approveUser": "1", - "applyUserName": "SIP管理员", - "applyTime": "2025-08-25 16:52", - "extendField1": "2", - "extendField2": null, - "taskId": "d9112b0c-8190-11f0-9558-00ff5af4ad6e", - "processInstanceId": "d9073ff2-8190-11f0-9558-00ff5af4ad6e", - "approveOpinion": null, - "approveStatus": null, - "approveTime": "2025-08-25 16:52", - "formKey": null, - "roleName": "超级管理员,鼎盛", - "recoveryType": null, - "variables": null - } - ], - "projectOrderInfo": { - "createBy": "1", - "createTime": "2025-05-30", - "updateBy": "1", - "updateTime": "2025-08-25 16:52:35", - "remark": "", - "id": 92, - "projectId": 92, - "projectCode": "V004592", - "projectName": "黑龙江省佳木斯附属第一医院2点胖终端云桌面项目", - "versionCode": "2", - "industryType": "zf", - "bgProperty": "SY", - "province": "黑龙江省", - "orderCode": "ZGXS-20250530HLJ001-VDI", - "customerName": "佳木斯大学附属第一医院", - "customerCode": "CU-HLJ-0002", - "customerPhone": "13352549898", - "customerUserName": "刘芸芸1111", - "shipmentAmount": 754169.99, - "orderStatus": "1", - "duty": "1", - "dutyName": "SIP管理员", - "agentName": "北京", - "agentCode": "BJS", - "notifier": "", - "city": "", - "businessPerson": "严浩", - "businessEmail": "", - "deleteFileId": null, - "businessPhone": "13512345457", - "currencyType": "rmb", - "partnerCode": "AGT-HLJ-0001", - "partnerName": "哈尔滨惠普天地电子有限公司", - "projectPartnerName": "哈尔滨惠普天地电子有限公司", - "productCodeList": null, - "actualPurchaseAmount": 777314.52, - "deliveryTime": "2025-06-04", - "deliveryTimeStart": null, - "deliveryTimeEnd": null, - "estimatedOrderTime": "2025-05-30", - "estimatedOrderTimeStart": null, - "estimatedOrderTimeEnd": null, - "orderEndTime": "2025-08-23", - "orderEndTimeStart": null, - "orderEndTimeEnd": null, - "updateTimeStart": null, - "updateTimeEnd": null, - "productSn": null, - "companyDelivery": "", - "notifierEmail": "", - "notifierPhone": "232", - "notifierAddress": "江西省南昌市高新区艾溪湖北路88号恒大中心A座1209室", - "dutyEmail": "mula.liu@163.com", - "dutyPhone": "18980500203", - "orderChannel": "1", - "partnerEmail": "", - "partnerUserName": "张树志", - "partnerPhone": "13936302299", - "systemUserId": "101", - "level": "02", - "processType": "0", - "processTemplate": "0", - "deliveryStatus": "1", - "signStatus": "0", - "outerStatus": "2", - "approveTime": "2025-08-19 16:46:26", - "approveTimeStart": null, - "approveTimeEnd": null, - "discountFold": 0.985, - "supplier": "紫光汇智信息技术有限公司", - "approve": null, - "contractFileList": [ - { - "createBy": null, - "createTime": null, - "updateBy": null, - "updateTime": null, - "remark": null, - "id": 27, - "orderId": 92, - "fileName": "AGT-AHS-0001.jpg", - "uploadUser": "101", - "uploadUserName": "chenhao", - "uploadTime": "2025-07-15", - "filePath": "/profile/2025/07/15/AGT-AHS-0001_20250715162608A004.jpg", - "fileType": "2", - "fileSort": "1", - "fileVersionCode": "2" - }, - { - "createBy": null, - "createTime": null, - "updateBy": null, - "updateTime": null, - "remark": null, - "id": 28, - "orderId": 92, - "fileName": "微信图片_2025-07-08_102450_731.png", - "uploadUser": "101", - "uploadUserName": "chenhao", - "uploadTime": "2025-07-15", - "filePath": "/profile/2025/07/15/微信图片_2025-07-08_102450_731_20250715163137A005.png", - "fileType": "2", - "fileSort": "3", - "fileVersionCode": "2" - }, - { - "createBy": null, - "createTime": null, - "updateBy": null, - "updateTime": null, - "remark": null, - "id": 30, - "orderId": 92, - "fileName": "AGT-AHS-0001 (4) (1).jpg", - "uploadUser": "101", - "uploadUserName": "chenhao", - "uploadTime": "2025-07-17", - "filePath": "/profile/2025/07/17/AGT-AHS-0001 (4) (1)_20250717145740A001.jpg", - "fileType": "2", - "fileSort": "0", - "fileVersionCode": "2" - } - ], - "configFileList": null, - "contractTableData": { - "2": [ - { - "createBy": null, - "createTime": null, - "updateBy": null, - "updateTime": null, - "remark": null, - "id": 30, - "orderId": 92, - "fileName": "AGT-AHS-0001 (4) (1).jpg", - "uploadUser": "101", - "uploadUserName": "chenhao", - "uploadTime": "2025-07-17", - "filePath": "/profile/2025/07/17/AGT-AHS-0001 (4) (1)_20250717145740A001.jpg", - "fileType": "2", - "fileSort": "0", - "fileVersionCode": "2" - }, - { - "createBy": null, - "createTime": null, - "updateBy": null, - "updateTime": null, - "remark": null, - "id": 27, - "orderId": 92, - "fileName": "AGT-AHS-0001.jpg", - "uploadUser": "101", - "uploadUserName": "chenhao", - "uploadTime": "2025-07-15", - "filePath": "/profile/2025/07/15/AGT-AHS-0001_20250715162608A004.jpg", - "fileType": "2", - "fileSort": "1", - "fileVersionCode": "2" - }, - { - "createBy": null, - "createTime": null, - "updateBy": null, - "updateTime": null, - "remark": null, - "id": -1, - "orderId": null, - "fileName": "(请上传现金折扣审批邮件信息).pdf/.jpg/.png", - "uploadUser": null, - "uploadUserName": null, - "uploadTime": null, - "filePath": null, - "fileType": null, - "fileSort": "2", - "fileVersionCode": null - }, - { - "createBy": null, - "createTime": null, - "updateBy": null, - "updateTime": null, - "remark": null, - "id": 28, - "orderId": 92, - "fileName": "微信图片_2025-07-08_102450_731.png", - "uploadUser": "101", - "uploadUserName": "chenhao", - "uploadTime": "2025-07-15", - "filePath": "/profile/2025/07/15/微信图片_2025-07-08_102450_731_20250715163137A005.png", - "fileType": "2", - "fileSort": "3", - "fileVersionCode": "2" - } - ] - }, - "softwareProjectProductInfoList": [ - { - "createBy": null, - "createTime": null, - "updateBy": null, - "updateTime": null, - "remark": "", - "id": 515, - "projectId": 92, - "productBomCode": "3130A4N9", - "productName": "VDI-ONEStor", - "model": "VDI-ONEStor-upgrade", - "productCode": null, - "productDesc": "H3C VDI云桌面分布式存储软件(VDI-ONEStor)-块存储标准版升级企业版License-管理2个物理CPU", - "quantity": 5, - "cataloguePrice": 62500.00, - "catalogueAllPrice": 312500.00, - "price": 53756.53, - "allPrice": 268782.65, - "allPriceDisCount": null, - "guidanceDiscount": 0.0800, - "vendorCode": "P001", - "discount": 0.8601, - "type": "1", - "value": "" - }, - { - "createBy": null, - "createTime": null, - "updateBy": null, - "updateTime": null, - "remark": "", - "id": 516, - "projectId": 92, - "productBomCode": "3130A4N9", - "productName": "VDI-ONEStor", - "model": "VDI-ONEStor-upgrade", - "productCode": null, - "productDesc": "H3C VDI云桌面分布式存储软件(VDI-ONEStor)-块存储标准版升级企业版License-管理2个物理CPU", - "quantity": 10, - "cataloguePrice": 62500.00, - "catalogueAllPrice": 625000.00, - "price": 47783.58, - "allPrice": 477835.80, - "allPriceDisCount": null, - "guidanceDiscount": 0.0800, - "vendorCode": "P001", - "discount": 0.7645, - "type": "1", - "value": "" - } - ], - "hardwareProjectProductInfoList": [ - { - "createBy": null, - "createTime": null, - "updateBy": null, - "updateTime": null, - "remark": "", - "id": 233, - "projectId": 92, - "productBomCode": "9801A5KA", - "productName": "胖终端x86一体机", - "model": "C6530V-38-G2", - "productCode": "9801H0BA", - "productDesc": "H3C C6530V G2 云终端一体机-Intel 6核 2.5GHz/8GB DDR4/256GB SSD/4*USB3.0/2*USB2.0/1*HDMI/23.8寸/1000M/Wi-Fi", - "quantity": 2, - "cataloguePrice": 39500.00, - "catalogueAllPrice": 79000.00, - "price": 3774.90, - "allPrice": 7549.80, - "allPriceDisCount": null, - "guidanceDiscount": 0.1000, - "vendorCode": "P001", - "discount": 0.0956, - "type": "2", - "value": null - } - ], - "maintenanceProjectProductInfoList": [ - { - "createBy": null, - "createTime": null, - "updateBy": null, - "updateTime": null, - "remark": "", - "id": 518, - "projectId": 92, - "productBomCode": "8813A3YB", - "productName": "现场维保-3Y", - "model": "SV-MA-SFT-3Y", - "productCode": null, - "productDesc": "H3C 软件技术支持服务(三年)", - "quantity": 2, - "cataloguePrice": 1.00, - "catalogueAllPrice": 2.00, - "price": 0.87, - "allPrice": 1.74, - "allPriceDisCount": null, - "guidanceDiscount": 0.3000, - "vendorCode": null, - "discount": 0.8700, - "type": "11", - "value": "3" - } - ] - }, - "user": { - "createBy": "admin", - "createTime": "2025-04-10 15:57:30", - "updateBy": "", - "updateTime": "2025-08-20 09:05:21", - "remark": "管理员", - "userId": 1, - "userIdList": null, - "deptId": 103, - "parentId": null, - "roleId": null, - "loginName": "admin", - "userName": "SIP管理员", - "userType": "00", - "email": "mula.liu@163.com", - "phonenumber": "18980500203", - "sex": "0", - "avatar": "/profile/avatar/2025/04/11/blob_20250411032004A001.png", - "status": "0", - "delFlag": "0", - "loginIp": "127.0.0.1", - "loginDate": "2025-08-20 09:05:21", - "pwdUpdateDate": "2025-04-11 14:54:45", - "dept": { - "createBy": null, - "createTime": null, - "updateBy": null, - "updateTime": null, - "remark": null, - "deptId": 103, - "parentId": 101, - "ancestors": "0,100,101", - "deptName": "软件开发事业部", - "orderNum": 1, - "leader": "", - "phone": null, - "email": null, - "status": "0", - "delFlag": null, - "parentName": null - }, - "roles": [ - { - "createBy": null, - "createTime": null, - "updateBy": null, - "updateTime": null, - "remark": null, - "roleId": 1, - "roleName": "超级管理员", - "roleKey": "admin", - "roleSort": "1", - "dataScope": "1", - "status": "0", - "delFlag": null, - "flag": false, - "menuIds": null, - "deptIds": null, - "permissions": null, - "admin": true - }, - { - "createBy": null, - "createTime": null, - "updateBy": null, - "updateTime": null, - "remark": null, - "roleId": 104, - "roleName": "鼎盛", - "roleKey": "ds", - "roleSort": "1", - "dataScope": "1", - "status": "0", - "delFlag": null, - "flag": false, - "menuIds": null, - "deptIds": null, - "permissions": [], - "admin": false - } - ], - "roleIds": null, - "postIds": null, - "admin": true - } - } -} -``` - -### 3.3 审批操作模块 -**功能描述**: 处理审批通过、拒绝等操作 - -**主要功能**: -- 审批意见输入 -- 审批结果提交 -- 操作结果反馈 - -**接口需求**: -```typescript -// 提交审批结果 -//审批 -POST /project/order/order/approve -参数:{ - allApproveUserName?: string; - /** - * 发起时间 - */ - applyTime?: string; - /** - * 发起人姓名 - */ - applyUserName?: string; - /** - * 审批意见 - */ - approveOpinion?: string; - /** - * 审批结果 3 通过 2 驳回 1待审批 - */ - approveStatus?: number; - approveTime?: string; - approveUser?: string; - /** - * 审批人姓名 - */ - approveUserName?: string; - /** - * 业务主键 - */ - businessKey?: string; - /** - * 创建者 - */ - createBy?: string; - /** - * 创建时间 - */ - createTime?: string; - /** - * 扩展字段1 - */ - extendField1?: string; - /** - * 扩展字段2 - */ - extendField2?: string; - formKey?: string; - id?: number; - nextAllApproveUserName?: string; - processInstanceId?: string; - /** - * 流程key - */ - processKey?: string; - /** - * 流程名称 - */ - processName?: string; - recoveryType?: number; - /** - * 备注 - */ - remark?: string; - roleName?: string; - taskId?: string; - /** - * 任务名称 - */ - taskName?: string; - /** - * 流程id - */ - todoId?: string; - /** - * 更新者 - */ - updateBy?: string; - /** - * 更新时间 - */ - updateTime?: string; - [property: string]: any; -} -``` - -## 4. 微信小程序适配 - -### 4.1 WebView适配 -- 设置viewport适配移动端 -- 处理微信小程序的安全域名限制 -- 适配微信小程序的返回机制 - -### 4.2 微信JS-SDK集成 -- 配置微信JS-SDK -- 实现分享功能 -- 处理网络状态监听 - -### 4.3 样式适配 -- 响应式设计 -- 安全区域适配(刘海屏等) -- 深色模式支持 - -## 5. 数据流设计 - -### 5.1 数据状态管理 -```typescript -interface AppState { - user: UserInfo; - orderList: Order[]; - currentOrder: Order | null; - loading: boolean; -} -``` - -### 5.2 API数据格式规范 +### 4.1 通用响应格式 ```typescript interface ApiResponse { - code: number; - message: string; - data: T; + code: number; // 0 表示成功 + msg: string | null; + rows: T; // 列表数据通常在这里 (注意:部分接口可能在 data 字段) + total?: number; // 分页总数 } +``` +### 4.2 核心API接口 + +#### 4.2.1 认证 (Auth) +- `POST /login`: 用户登录 (FormData: username, password, rememberMe) + +#### 4.2.2 订单 (Order) +- `POST /project/order/list`: 获取待审批订单列表 + - 参数: `approve="approve"`, `page`, `pageSize`, `keyword` +- `POST /flow/completed/list`: 获取已审批订单列表 + - 参数: `page`, `pageSize`, `businessName`, `processKeyList` +- `GET /project/order/h5/approve/{id}`: 获取订单详情 +- `POST /project/order/order/approve`: 提交订单审批 + - 参数: `todoId`, `approveStatus`, `approveOpinion`, `variables`, `taxRateData` + +#### 4.2.3 采购 (Purchase) +- `GET /sip/purchaseorder/approveList`: 获取采购待审批列表 + - 参数: `page`, `pageSize`, `keyword` +- `POST /flow/completed/list`: 获取采购已审批列表 (复用流程接口) + - 参数: `processKeyList` (如 `['purchase_order_online']`) +- `GET /sip/purchaseorder/code/{purchaseNo}`: 获取采购详情 +- `POST /flow/todo/approve`: 提交采购审批 (注意与订单审批接口不同) +- `POST /flow/completed/all/list`: 获取采购审批历史 + +## 5. 数据模型 (TypeScript Types) + +### 5.1 订单相关 +```typescript +// 订单信息 interface Order { - id: string; - title: string; - status: 'pending' | 'approved' | 'rejected'; - createdAt: string; - applicant: string; - content: string; - attachments?: string[]; - approvalHistory: ApprovalRecord[]; -} - -interface ApprovalRecord { - id: string; - approver: string; - action: 'approve' | 'reject'; - comment: string; - createdAt: string; -} -``` - -## 6. 页面路由设计 - -```typescript -const routes = [ - { - path: '/', - redirect: '/login' - }, - { - path: '/login', - name: 'Login', - component: () => import('@/views/Login/index.vue'), - meta: { - title: '系统登录', - requiresAuth: false - } - }, - { - path: '/list', - name: 'Home', - component: () => import('@/views/Home/index.vue'), - meta: { - title: '审批中心', - requiresAuth: true - } - }, - { - path: '/detail/:id', - name: 'OrderDetail', - component: () => import('@/views/Detail/index.vue'), - meta: { - title: '订单详情', - requiresAuth: true - } - }, - { - path: '/purchase-detail/:id', - name: 'PurchaseDetail', - component: () => import('@/views/PurchaseDetail/index.vue'), - meta: { - title: '采购详情', - requiresAuth: true - } - } -] -``` - -**路由说明**: -- `/login`: 登录页面,不需要认证 -- `/list`: 审批中心主页面,包含左侧抽屉菜单和审批列表 - - 默认展示订单审批列表 - - 可通过抽屉菜单切换到采购审批列表 -- `/detail/:id`: 订单详情页面 - - 支持 `readonly=true` 查询参数用于只读模式 -- `/purchase-detail/:id`: 采购详情页面(独立实现) - - 展示采购单基本信息和产品列表 - - 采购单号作为路由参数 - -## 7. 性能优化策略 - -### 7.1 代码层面 -- 组件懒加载 -- 图片懒加载 -- API请求缓存 -- 防抖和节流 - -### 7.2 构建优化 -- 代码分割 -- 资源压缩 -- CDN部署 - -## 8. 安全考虑 - -### 8.1 数据安全 -- HTTPS通信 -- 接口鉴权 -- 敏感信息加密 - -### 8.2 XSS防护 -- 输入内容过滤 -- CSP策略配置 - -## 9. 测试策略 - -### 9.1 单元测试 -- 组件测试 -- 工具函数测试 - -### 9.2 集成测试 -- API接口测试 -- 页面交互测试 - -### 9.3 兼容性测试 -- 微信小程序WebView测试 -- 不同设备适配测试 - -## 10. 部署方案 - -### 10.1 开发环境 -- 本地开发服务器 -- 热重载支持 - -### 10.2 生产环境 -- 静态资源CDN部署 -- 域名HTTPS配置 -- 微信小程序业务域名配置 - ---- - -**文档版本**: v1.0 -**创建时间**: 2025-08-27 -**负责人**: 开发团队 - -## 4. 技术架构 - -### 4.1 技术栈选型 - -#### 4.1.1 前端技术栈 -- **Vue 3.3.4**: 采用Composition API,提供更好的类型支持和逻辑复用 -- **TypeScript**: 提供静态类型检查,提高代码质量和开发效率 -- **Vite 4.4.9**: 现代化构建工具,提供快速的开发体验 -- **Vue Router 4.2.4**: 单页应用路由管理 -- **Pinia 2.1.6**: 轻量级状态管理库,替代Vuex -- **Vant 4.6.6**: 移动端UI组件库,适配微信小程序H5 -- **Axios 1.5.0**: HTTP请求库,支持请求/响应拦截 -- **Sass**: CSS预处理器,提供变量、嵌套等高级功能 - -#### 4.1.2 开发工具 -- **ESLint**: 代码质量检查 -- **Prettier**: 代码格式化 -- **unplugin-auto-import**: 自动导入Vue、Router、Pinia等API -- **unplugin-vue-components**: 自动导入Vant组件 -- **@vant/touch-emulator**: 桌面端触摸事件模拟 - -### 4.2 项目架构 - -#### 4.2.1 目录结构 -``` -src/ -├── api/ # API接口层 -│ ├── auth.ts # 认证相关接口 -│ └── order.ts # 订单相关接口 -├── router/ # 路由配置 -├── store/ # 状态管理 -│ ├── auth.ts # 认证状态 -│ └── order.ts # 订单状态 -├── types/ # TypeScript类型定义 -├── utils/ # 工具函数 -│ ├── http.ts # HTTP客户端封装 -│ └── index.ts # 通用工具函数 -├── views/ # 页面组件 -│ ├── Login/ # 登录页 -│ ├── List/ # 订单列表页 -│ └── Detail/ # 订单详情页 -└── styles/ # 全局样式 -``` - -#### 4.2.2 架构设计原则 -- **分层架构**: View层 → Store层 → API层 → 后端服务 -- **组件化**: 页面拆分为可复用的组件 -- **类型安全**: 全面使用TypeScript进行类型约束 -- **响应式设计**: 适配不同屏幕尺寸 -- **状态管理**: 集中管理应用状态,支持数据持久化 - -### 4.3 核心模块设计 - -#### 4.3.1 认证模块 (Auth) -**功能职责**: -- 用户登录/登出 -- 认证状态管理 -- 路由权限控制 -- 会话持久化 - -**技术实现**: -- Session基于Cookie的认证机制 -- localStorage存储认证状态 -- 路由守卫实现权限控制 -- 支持"记住密码"功能 - -**关键代码**: -```typescript -// 认证状态管理 -interface AuthState { - token: string | null - userInfo: any | null - isAuthenticated: boolean -} - -// 路由守卫 -router.beforeEach((to, from, next) => { - const requiresAuth = to.matched.some(record => record.meta.requiresAuth !== false) - const authStore = useAuthStore(store) - const isAuthenticated = authStore.isAuthenticated || localStorage.getItem('isAuthenticated') === 'true' - - if (requiresAuth && !isAuthenticated) { - next('/login') - } else { - next() - } -}) -``` - -#### 4.3.2 订单管理模块 (Order) -**功能职责**: -- 双Tab订单列表管理(待审批/已审批) -- 订单详情获取 -- 审批操作处理 -- 数据状态管理 -- 只读模式支持 - -**技术实现**: -- 双Tab架构,独立状态管理 -- 无限滚动加载,支持分页 -- 搜索功能(不同Tab对应不同搜索字段) -- 下拉刷新 -- 数据缓存机制 -- 路由参数控制只读模式 - -**关键特性**: -- **状态隔离**: 待审批和已审批列表状态完全独立 -- **智能搜索**: 根据当前Tab自动切换搜索字段和接口 -- **只读模式**: 通过URL参数`readonly=true`控制详情页只读 -- **性能优化**: Tab切换时保持各自滚动位置和搜索状态 - -**数据模型**: -```typescript -interface Order { - id: number - projectCode: string - projectName: string - customerName: string - shipmentAmount: number - orderStatus: OrderStatus + id: number; + orderCode: string; + projectName: string; + customerName: string; + shipmentAmount: number; + orderStatus: '0' | '1' | '2'; // ... 其他字段 } +// 订单详情响应 interface OrderDetailResponse { projectOrderInfo: Order & { - contractFileList: AttachmentFile[] - softwareProjectProductInfoList: ProductInfo[] - hardwareProjectProductInfoList: ProductInfo[] - maintenanceProjectProductInfoList: ProductInfo[] - } - approveLog: ApprovalRecord[] - user: UserInfo + contractFileList: AttachmentFile[]; + softwareProjectProductInfoList: ProductInfo[]; + hardwareProjectProductInfoList: ProductInfo[]; + // ... + }; + approveLog: ApprovalRecord[]; + user: UserInfo; } ``` -#### 4.3.3 HTTP客户端模块 -**功能职责**: -- 统一HTTP请求封装 -- 请求/响应拦截 -- 错误处理 -- 认证token自动添加 - -**技术实现**: +### 5.2 采购相关 ```typescript -class HttpClient { - private instance: AxiosInstance - - constructor(baseURL: string = '/api') { - this.instance = axios.create({ - baseURL, - timeout: 30000, - headers: { - 'Content-Type': 'application/json;charset=UTF-8' - } - }) - this.setupInterceptors() - } - - private setupInterceptors() { - // 请求拦截器 - 添加token - this.instance.interceptors.request.use((config) => { - const token = localStorage.getItem('token') - if (token) { - config.headers.Authorization = `Bearer ${token}` - } - return config - }) - - // 响应拦截器 - 统一错误处理 - this.instance.interceptors.response.use( - (response) => response, - (error) => { - // 401/302 重定向到登录页 - if (error.response?.status === 401 || error.response?.status === 302) { - localStorage.removeItem('isAuthenticated') - window.location.href = '/login' - } - return Promise.reject(error) - } - ) - } +// 采购单列表项 +interface Purchase { + id: number; + purchaseNo: string; + approveStatus: string; + vendorName: string; + ownerName: string; + totalAmount: number; + createTime: string; +} + +// 采购详情 +interface PurchaseDetail { + id: number; + purchaseNo: string; + purchaserName: string; + warehouseName: string; + payMethod: string; + omsPurchaseOrderItemList: PurchaseOrderItem[]; + // ... +} + +// 采购产品项 +interface PurchaseOrderItem { + productCode: string; + productModel: string; + productDescription: string; + quantity: number; + price: number; } ``` -### 4.4 微信小程序适配 +## 6. 部署与环境 -#### 4.4.1 WebView环境检测 -```javascript -// 微信小程序webview适配 -if (window.__wxjs_environment === 'miniprogram') { - console.log('Running in WeChat MiniProgram WebView'); -} -``` +### 6.1 环境变量 +- `VITE_API_BASE_URL`: 后端API地址 +- `VITE_FILE_BASE_URL`: 文件服务器地址 (用于图片/PDF预览) -#### 4.4.2 移动端优化 -- **触摸事件**: 使用@vant/touch-emulator在桌面端模拟触摸 -- **视口设置**: 固定viewport,禁止缩放 -- **防止双指缩放**: JavaScript阻止多点触控事件 +### 6.2 微信小程序适配 +- 使用 `viewport` meta 标签禁止缩放。 +- 检测 `window.__wxjs_environment` 识别环境。 +- 使用 `@vant/touch-emulator` 在桌面端调试触摸事件。 -```html - -``` +## 7. 更新日志 -### 4.5 构建和部署 - -#### 4.5.1 开发环境配置 -```javascript -// vite.config.ts -export default defineConfig({ - server: { - host: '0.0.0.0', - port: 3000, - proxy: { - '/api': { - target: 'http://localhost:28080', - changeOrigin: true, - rewrite: (path) => path.replace(/^\/api/, '') - } - } - } -}) -``` - -#### 4.5.2 环境变量配置 -- **.env.development**: 开发环境配置 -- **.env.production**: 生产环境配置 -- **VITE_API_BASE_URL**: API服务地址 -- **VITE_FILE_BASE_URL**: 文件服务地址 - -#### 4.5.3 构建优化 -- **代码分割**: 按页面自动分割代码包 -- **资源优化**: 静态资源版本化管理 -- **TypeScript编译**: 严格类型检查 -- **ES2015兼容**: 支持现代浏览器特性 - -## 5. 接口设计 - -### 5.1 认证接口 - -#### 5.1.1 用户登录 -**接口地址**: `POST /login` - -**请求参数**: FormData格式 -``` -username: string // 用户名 -password: string // 密码 -rememberMe: boolean // 记住密码 -``` - -**响应格式**: -```json -{ - "code": 0, - "msg": "操作成功", - "data": { - "token": "jwt_token", - "userInfo": {...} - } -} -``` - -### 5.2 订单接口 - -#### 5.2.1 获取订单列表 -**接口地址**: `POST /project/order/list` - -**请求参数**: FormData格式 -``` -approve: string // 固定值 "approve" -page: number // 页码 -pageSize: number // 每页数量 -keyword: string // 搜索关键词(可选) -``` - -**响应格式**: -```json -{ - "code": 0, - "msg": "操作成功", - "data": { - "total": 100, - "rows": [...] - } -} -``` - -#### 5.2.2 获取订单详情 -**接口地址**: `GET /project/order/h5/approve/{id}` - -**响应格式**: -```json -{ - "code": 0, - "msg": "操作成功", - "data": { - "projectOrderInfo": {...}, - "approveLog": [...], - "user": {...} - } -} -``` - -#### 5.2.3 获取已审批列表 -**接口地址**: `POST /flow/completed/list` - -**请求参数**: FormData格式 -``` -page: number // 页码 -pageSize: number // 每页数量 -businessName: string // 合同名称搜索(可选) -``` - -**响应格式**: -```json -{ - "code": 0, - "msg": "操作成功", - "data": { - "total": 100, - "rows": [ - { - "allApproveUserName": "chenhao", - "applyTime": "2025-09-19 17:06", - "applyUserName": "chenhao", - "approveOpinion": "经审查无误,予以批准", - "approveStatus": 3, - "approveTime": "2025-09-19 17:07", - "approveUser": "101", - "approveUserName": "chenhao", - "businessId": 257, - "businessKey": "ZGXV-20250919BJS001", - "businessName": "测试-重庆xx学校云桌面项目", - "processInstanceId": "58ce6889-9536-11f0-8f98-00ff08deec4d", - "processKey": "order_approve_online", - "processName": "订单审批流程", - "roleName": "商务,鼎盛", - "taskId": "fb6c16dd-9537-11f0-8f98-00ff08deec4d", - "taskName": "领导1", - "todoId": "1968965000342323200" - } - ] - } -} -``` - -#### 5.2.4 提交审批结果 -**接口地址**: `POST /project/order/order/approve` - -**请求参数**: FormData格式,支持复杂对象序列化 -``` -// 基本参数 -todoId: string -approveStatus: number // 1-待审批 2-驳回 3-通过 -approveOpinion: string // 审批意见 - -// 变量参数 (动态) -variables[key]: value - -// 税率数据 (数组对象) -taxRateData[0].field: value -``` - -## 6. 数据模型 - -### 6.1 核心实体 - -#### 6.1.1 订单实体 (Order) -```typescript -interface Order { - id: number // 订单ID - projectId: number // 项目ID - projectCode: string // 项目编码 - projectName: string // 项目名称 - customerName: string // 客户名称 - customerCode: string // 客户编码 - shipmentAmount: number // 发货金额 - orderStatus: OrderStatus // 订单状态: '0'-待审批 '1'-已审批 '2'-已拒绝 - createTime: string // 创建时间 - updateTime: string // 更新时间 - // ... 其他业务字段 -} -``` - -#### 6.1.2 审批记录 (ApprovalRecord) -```typescript -interface ApprovalRecord { - id?: number // 记录ID - todoId: string // 待办事项ID - taskName: string // 任务名称 - approveUserName: string // 审批人姓名 - approveStatus?: ApprovalStatus // 审批状态: 1-待审批 2-驳回 3-通过 - approveOpinion?: string // 审批意见 - approveTime: string // 审批时间 - roleName: string // 角色名称 -} -``` - -#### 6.1.3 产品信息 (ProductInfo) -```typescript -interface ProductInfo { - id: number // 产品ID - productName: string // 产品名称 - model: string // 型号 - quantity: number // 数量 - cataloguePrice: number // 目录价格 - price: number // 实际价格 - discount: number // 折扣 - type: string // 产品类型 -} -``` - -#### 6.1.4 附件文件 (AttachmentFile) -```typescript -interface AttachmentFile { - id: number // 文件ID - fileName: string // 文件名称 - uploadUser: string // 上传用户 - uploadTime: string // 上传时间 - filePath: string // 文件路径 - fileType: string // 文件类型 -} -``` - -#### 6.1.5 已审批列表项 (CompletedApprovalItem) -```typescript -interface CompletedApprovalItem { - allApproveUserName: string // 所有审批人姓名 - applyTime: string // 申请时间 - applyUserName: string // 申请人姓名 - approveOpinion: string // 审批意见 - approveStatus: ApprovalStatus // 审批状态: 2-驳回,3-通过,其他-提交 - approveTime: string // 审批时间 - approveUser: string // 审批人ID - approveUserName: string // 审批人姓名 - businessId: number // 业务ID - businessKey: string // 业务编号 - businessName: string // 合同名称 - nextAllApproveUserName: string // 下一步审批人 - processInstanceId: string // 流程实例ID - processKey: string // 流程编码 - processName: string // 流程名称 - roleName: string // 角色名称 - taskId: string // 任务ID - taskName: string // 任务名称 - todoId: string // 待办事项ID -} -``` - -#### 6.1.6 查询参数类型 -```typescript -// 已审批列表查询参数 -interface CompletedListParams { - businessName?: string // 合同名称搜索 - page: number // 页码 - pageSize: number // 每页数量 -} -``` - -## 7. 性能优化 - -### 7.1 前端性能优化 - -#### 7.1.1 代码层面优化 -- **按需加载**: 路由组件懒加载,减少初始包体积 -- **组件缓存**: 合理使用keep-alive缓存组件状态 -- **防抖节流**: 搜索输入等操作使用防抖处理 -- **虚拟滚动**: 大数据列表使用虚拟滚动技术 - -#### 7.1.2 资源优化 -- **图片压缩**: 静态图片资源压缩和格式优化 -- **代码分割**: Vite自动代码分割和Tree Shaking -- **CDN加速**: 静态资源使用CDN分发 -- **缓存策略**: 合理设置浏览器缓存策略 - -#### 7.1.3 网络优化 -- **请求合并**: 相关数据请求合并减少网络往返 -- **数据缓存**: Store层实现数据缓存机制 -- **离线支持**: Service Worker实现基础离线功能 -- **预加载**: 关键数据提前预加载 - -### 7.2 移动端优化 - -#### 7.2.1 交互优化 -- **触摸反馈**: 所有可点击元素提供视觉反馈 -- **手势支持**: 支持下拉刷新、上拉加载等手势 -- **防误触**: 避免过小的点击区域 -- **加载状态**: 提供明确的加载和空状态提示 - -#### 7.2.2 性能监控 -- **错误监控**: 集成错误上报和监控 -- **性能监控**: 关键性能指标监控 -- **用户行为**: 用户操作路径分析 -- **兼容性**: 不同设备和浏览器兼容性测试 - -## 8. 安全设计 - -### 8.1 认证安全 -- **Session管理**: 基于服务端Session的认证机制 -- **超时处理**: 会话超时自动重定向登录页 -- **权限控制**: 前端路由权限控制 -- **敏感信息**: 避免在前端存储敏感信息 - -### 8.2 数据安全 -- **输入验证**: 前端表单数据验证 -- **XSS防护**: 用户输入内容转义处理 -- **HTTPS**: 生产环境强制使用HTTPS -- **CORS**: 正确配置跨域访问策略 - -### 8.3 接口安全 -- **参数校验**: 接口参数类型和格式校验 -- **错误处理**: 统一错误处理,避免敏感信息泄露 -- **请求限制**: 防止恶意频繁请求 -- **数据脱敏**: 敏感数据展示脱敏处理 - -## 9. 测试策略 - -### 9.1 单元测试 -- **组件测试**: Vue组件单元测试 -- **工具函数**: 纯函数逻辑测试 -- **Store测试**: 状态管理逻辑测试 -- **覆盖率**: 关键逻辑代码覆盖率90%+ - -### 9.2 集成测试 -- **API测试**: 前后端接口集成测试 -- **用户流程**: 完整业务流程端到端测试 -- **兼容性**: 不同浏览器和设备兼容性测试 -- **性能测试**: 关键性能指标测试 - -### 9.3 用户测试 -- **可用性测试**: 用户界面易用性测试 -- **体验测试**: 用户操作体验测试 -- **回归测试**: 版本迭代回归测试 -- **压力测试**: 高并发场景压力测试 - -## 10. 部署运维 - -### 10.1 部署流程 -1. **代码构建**: `npm run build` 生成生产包 -2. **静态部署**: 将dist目录部署到Web服务器 -3. **反向代理**: Nginx配置API代理和静态文件服务 -4. **域名配置**: 配置生产域名和HTTPS证书 - -### 10.2 监控告警 -- **错误监控**: JavaScript错误自动上报 -- **性能监控**: 页面加载性能监控 -- **业务监控**: 关键业务指标监控 -- **告警通知**: 异常情况及时告警通知 - -### 10.3 版本管理 -- **版本号**: 语义化版本号管理 -- **变更日志**: 详细记录版本变更内容 -- **回滚机制**: 快速版本回滚能力 -- **灰度发布**: 分批次灰度发布策略 - ---- - -## 11. 更新日志 +### v1.4 - 2026-01-06 (Current) +**文档同步更新** +- 根据实际代码库结构和API实现更新了概要设计文档。 +- 明确了订单审批与采购审批使用不同的提交接口。 +- 完善了采购模块的接口定义和数据模型描述。 +- 确认了项目采用 Vue 3.3 + Vite 4.4 + Vant 4.6 技术栈。 ### v1.3 - 2025-12-01 **功能完善:实现采购详情页面** - -**完成功能**: -1. **类型定义扩展** (`src/types/index.ts`) - - 新增 PurchaseOrderItem 采购产品项类型 - - 新增 PurchaseDetail 采购详情类型 - - 定义详情页面所需的所有字段类型 - -2. **状态管理增强** (`src/store/purchase.ts`) - - 添加详情相关状态:currentPurchase、detailLoading - - 实现 fetchPurchaseDetail() 获取采购详情方法 - - 实现 clearCurrentPurchase() 清空详情方法 - - 添加 purchaseItems getter 获取采购产品列表 - -3. **采购详情页面** (`src/views/PurchaseDetail/index.vue`) - - 独立实现采购详情页面(不复用订单详情组件) - - **订单信息Tab**:展示采购单号、发起日期、采购员、联系方式、入库仓、付款方式、负责人、备注等信息 - - **采购列表Tab**:展示产品编码、型号、描述、数量、单价,自动计算小计和总金额 - - 支持产品列表滚动查看 - - 实现总金额自动计算 - -4. **路由配置更新** (`src/router/index.ts`) - - 更新采购详情路由,使用独立的 PurchaseDetail 组件 - - 路由参数为采购单号 purchaseNo - -5. **接口对接** - - 对接采购详情接口:GET /sip/purchaseorder/code/{purchaseNo} - - 完整展示采购单基本信息和产品列表 - -**设计亮点**: -- 采购详情页面采用双Tab设计,信息分类清晰 -- 产品列表采用卡片式展示,每个产品独立展示完整信息 -- 自动计算产品小计和总金额,方便用户快速了解采购成本 -- UI/UX与订单详情保持一致的设计风格 - ---- +- 独立实现采购详情页面 `PurchaseDetail`。 +- 对接采购详情接口和状态管理。 ### v1.2 - 2025-12-01 **功能实现:对接采购审批接口** - -**完成功能**: -1. **类型定义** (`src/types/index.ts`) - - 新增采购订单信息类型 Purchase - - 新增采购列表查询参数类型 PurchaseListParams - -2. **API接口层** (`src/api/purchase.ts`) - - 实现获取采购待审批列表接口 (GET /sip/purchaseorder/approveList) - - 预留已审批列表、详情、审批提交接口 - -3. **状态管理** (`src/store/purchase.ts`) - - 创建采购状态管理 store - - 实现待审批列表加载、搜索、刷新功能 - - 实现已审批列表基础架构(待对接) - - 支持分页加载和无限滚动 - -4. **采购列表页面** (`src/views/Purchase/index.vue`) - - 对接真实接口获取采购待审批数据 - - 展示字段:采购单号、审批状态、制造商名称、汇智负责人、采购金额 - - 支持搜索、下拉刷新、上拉加载更多 - - 保持与订单审批页面一致的UI/UX - -**接口对接状态**: -- ✅ 待审批列表:GET /sip/purchaseorder/approveList -- ✅ 已审批列表:GET /sip/purchaseorder/approved/list -- ✅ 采购详情:GET /sip/purchaseorder/code/{purchaseNo} -- ⏳ 审批提交:待确认接口地址 - ---- +- 实现采购待审批列表。 +- 预留已审批列表对接逻辑。 ### v1.1 - 2025-12-01 -**架构优化:添加左侧抽屉菜单支持多审批类型** - -**新增功能**: -1. **审批中心主页面** (`src/views/Home/index.vue`) - - 新增左侧抽屉菜单导航 - - 支持多种审批类型切换 - - 统一管理顶部导航栏和退出登录功能 - - 抽屉菜单占屏幕70%宽度,支持遮罩层关闭 - -2. **采购审批模块** (`src/views/Purchase/index.vue`) - - 参照订单审批实现采购审批列表页面 - - 支持待审批和已审批双Tab切换 - - 支持采购单号和合同名称搜索 - - 接口部分预留,待后续对接 - -**架构调整**: -1. **路由重构** - - `/list` 路径改为指向审批中心主页面 - - 新增 `/purchase-detail/:id` 采购详情路由 - - 完善路由元信息配置 - -2. **订单审批列表组件优化** - - 移除独立的顶部导航栏和退出按钮 - - 作为子组件嵌入到审批中心主页面 - - 保持原有功能和交互逻辑不变 - -**菜单项配置**: -- 订单审批 (icon: notes-o) -- 采购审批 (icon: shopping-cart-o) - -**后续扩展**: -- 左侧抽屉菜单采用配置化设计,便于后续添加更多审批类型 -- 菜单项包含图标、标题、路由等完整配置 -- 支持菜单项的激活状态显示和权限控制 - ---- - -**文档版本**: v1.3 -**更新时间**: 2025-12-01 -**负责人**: 开发团队 \ No newline at end of file +**架构优化:添加左侧抽屉菜单** +- 重构 `Home` 页面,引入抽屉菜单切换 "订单审批" 和 "采购审批"。