潘的第一次 commit

This commit is contained in:
panchengyong
2026-02-27 23:50:25 +08:00
commit 10b6d0099a
117 changed files with 32547 additions and 0 deletions

View File

@@ -0,0 +1,156 @@
import { describe, it, expect, vi, beforeEach } from 'vitest'
import {
getCustomerList,
getCustomerDetail,
createCustomer,
updateCustomer,
deleteCustomer,
updateCustomerStatus,
type Customer,
type CustomerQuery
} from '../customer'
const mockGet = vi.fn()
const mockPost = vi.fn()
const mockPut = vi.fn()
const mockDelete = vi.fn()
vi.mock('../request', () => ({
default: {
get: (...args: unknown[]) => mockGet(...args),
post: (...args: unknown[]) => mockPost(...args),
put: (...args: unknown[]) => mockPut(...args),
delete: (...args: unknown[]) => mockDelete(...args)
}
}))
describe('customer API', () => {
beforeEach(() => {
vi.clearAllMocks()
})
describe('getCustomerList', () => {
it('requests list and maps rows with compat fields', async () => {
mockGet.mockResolvedValue({
rows: [
{
clientId: 1,
clientCode: 'C001',
clientName: '客户A',
clientNick: 'A',
contact1: '张三',
contact1Tel: '13800001111',
address: '深圳市',
enableFlag: 'Y',
createTime: '2026-01-25 10:00:00'
}
],
total: 1
})
const res = await getCustomerList({
clientCode: 'C001',
pageNum: 1,
pageSize: 10
})
expect(mockGet).toHaveBeenCalledWith('/erp/sl/client/list', {
params: expect.objectContaining({ clientCode: 'C001', pageNum: 1, pageSize: 10 })
})
expect(res.list).toHaveLength(1)
expect(res.total).toBe(1)
expect(res.list[0]).toMatchObject({
clientId: 1,
clientCode: 'C001',
clientName: '客户A',
id: 1,
code: 'C001',
name: '客户A',
contact: '张三',
phone: '13800001111'
})
})
it('maps name param to clientName', async () => {
mockGet.mockResolvedValue({ rows: [], total: 0 })
await getCustomerList({ name: '测试' } as CustomerQuery)
expect(mockGet).toHaveBeenCalledWith('/erp/sl/client/list', {
params: expect.objectContaining({ clientName: '测试' })
})
})
it('handles res.list or res.data.rows', async () => {
mockGet.mockResolvedValue({ list: [{ clientId: 2, clientCode: 'C002', clientName: 'B' }], total: 1 })
const res = await getCustomerList({})
expect(res.list).toHaveLength(1)
expect(res.list[0]?.clientCode).toBe('C002')
})
})
describe('getCustomerDetail', () => {
it('fetches detail and maps compat fields', async () => {
mockGet.mockResolvedValue({
data: {
clientId: 1,
clientCode: 'C001',
clientName: '客户A',
contact1: '李四',
contact1Tel: '13900002222'
}
})
const res = await getCustomerDetail(1)
expect(mockGet).toHaveBeenCalledWith('/erp/sl/client/1')
expect(res.clientId).toBe(1)
expect(res.id).toBe(1)
expect(res.code).toBe('C001')
expect(res.name).toBe('客户A')
expect(res.contact).toBe('李四')
expect(res.phone).toBe('13900002222')
})
})
describe('createCustomer', () => {
it('POSTs payload', async () => {
mockPost.mockResolvedValue(undefined)
const data: Partial<Customer> = {
clientCode: 'C003',
clientName: '客户C',
enableFlag: 'Y'
}
await createCustomer(data)
expect(mockPost).toHaveBeenCalledWith('/erp/sl/client', data)
})
})
describe('updateCustomer', () => {
it('PUTs payload', async () => {
mockPut.mockResolvedValue(undefined)
const data: Partial<Customer> = { clientId: 1, clientName: '更新名' }
await updateCustomer(data)
expect(mockPut).toHaveBeenCalledWith('/erp/sl/client', data)
})
})
describe('deleteCustomer', () => {
it('DELETEs single id', async () => {
mockDelete.mockResolvedValue(undefined)
await deleteCustomer(1)
expect(mockDelete).toHaveBeenCalledWith('/erp/sl/client/1')
})
it('DELETEs comma-separated ids', async () => {
mockDelete.mockResolvedValue(undefined)
await deleteCustomer([1, 2, 3])
expect(mockDelete).toHaveBeenCalledWith('/erp/sl/client/1,2,3')
})
})
describe('updateCustomerStatus', () => {
it('PUTs clientId and enableFlag', async () => {
mockPut.mockResolvedValue(undefined)
await updateCustomerStatus(1, 'N')
expect(mockPut).toHaveBeenCalledWith('/erp/sl/client', { clientId: 1, enableFlag: 'N' })
})
})
})

View File

@@ -0,0 +1,58 @@
import axios from 'axios'
// 创建一个专门用于登录相关的 axios 实例(不带 /erp 前缀)
const authRequest = axios.create({
baseURL: '',
timeout: 30000
})
// 登录方法
export function login(username: string, password: string, code: string, uuid: string) {
return authRequest({
url: '/login',
method: 'post',
data: { username, password, code, uuid }
}).then(res => res.data)
}
// 注册方法
export function register(data: { username: string; password: string; confirmPassword: string }) {
return authRequest({
url: '/register',
method: 'post',
data
}).then(res => res.data)
}
// 获取用户详细信息
export function getInfo() {
const token = localStorage.getItem('Admin-Token')
return authRequest({
url: '/getInfo',
method: 'get',
headers: {
Authorization: token ? `Bearer ${token}` : ''
}
}).then(res => res.data)
}
// 退出方法
export function logout() {
const token = localStorage.getItem('Admin-Token')
return authRequest({
url: '/logout',
method: 'post',
headers: {
Authorization: token ? `Bearer ${token}` : ''
}
}).then(res => res.data)
}
// 获取验证码
export function getCodeImg() {
return authRequest({
url: '/captchaImage',
method: 'get',
timeout: 20000
}).then(res => res.data)
}

View File

@@ -0,0 +1,96 @@
import request from './request'
export interface CheckinLine {
lineId: number
checkinId: number
checkinCode: string
lineNo: number
orderLineId?: number
trackCode?: string
itemId: number
itemCode: string
itemName: string
specification?: string
unitName?: string
orderQuantity?: number
quantity: number
stockedQuantity?: number
remark?: string
}
export interface Checkin {
checkinId: number
checkinCode: string
checkinDate: string
status: string
businessType: string
orderId?: number
orderCode?: string
supplierId?: number
supplierName?: string
warehouseId?: number
warehouseName?: string
totalQuantity?: number
stockedQuantity?: number
remark?: string
operatorName?: string
approverName?: string
approveDate?: string
lines: CheckinLine[]
createTime?: string
}
export interface CheckinQuery {
trackCode?: string
checkinCode?: string
supplierName?: string
itemCode?: string
itemName?: string
beginDate?: string
endDate?: string
status?: string
pageNum?: number
pageSize?: number
}
export interface CheckinListResponse {
rows: Checkin[]
total: number
}
// 获取采购到货单列表
export function getCheckinList(params: CheckinQuery): Promise<CheckinListResponse> {
return request.get('/erp/po/checkin/list', { params }).then((res: any) => {
return {
rows: res.rows || [],
total: res.total || 0
}
})
}
// 获取采购到货单详情
export function getCheckinDetail(checkinId: number): Promise<Checkin> {
return request.get(`/erp/po/checkin/${checkinId}`).then((res: any) => {
return res.data
})
}
// 新增采购到货单
export function createCheckin(data: Partial<Checkin>): Promise<void> {
return request.post('/erp/po/checkin', data)
}
// 更新采购到货单
export function updateCheckin(data: Partial<Checkin>): Promise<void> {
return request.put('/erp/po/checkin', data)
}
// 删除采购到货单
export function deleteCheckin(checkinIds: string): Promise<void> {
return request.delete(`/erp/po/checkin/${checkinIds}`)
}
// 注意:采购到货单审核接口后端暂未实现
// export function approveCheckin(checkinId: number): Promise<void> {
// return request.post(`/erp/po/checkin/audit/${checkinId}`)
// }

View File

@@ -0,0 +1,63 @@
import request from './request'
export interface Contract {
contractId?: number
contractCode?: string
contractName?: string
clientId?: number
clientCode?: string
clientName?: string
contractDate?: string
startDate?: string
endDate?: string
status?: string
totalAmount?: number
remark?: string
createTime?: string
tenantId?: string
}
export interface ContractQuery {
contractCode?: string
clientName?: string
status?: string
pageNum?: number
pageSize?: number
}
export interface ContractListResponse {
list: Contract[]
total: number
}
// 获取销售合同列表
export function getContractList(params: ContractQuery): Promise<ContractListResponse> {
return request.get('/sl/contract/list', { params }).then((res: any) => {
return {
list: res.rows || [],
total: res.total || 0
}
})
}
// 获取销售合同详情
export function getContractDetail(id: number): Promise<Contract> {
return request.get(`/sl/contract/${id}`).then((res: any) => {
return res.data
})
}
// 新增销售合同
export function createContract(data: Partial<Contract>): Promise<void> {
return request.post('/sl/contract', data)
}
// 更新销售合同
export function updateContract(id: number, data: Partial<Contract>): Promise<void> {
return request.put('/sl/contract', { ...data, contractId: id })
}
// 删除销售合同
export function deleteContract(id: number): Promise<void> {
return request.delete(`/sl/contract/${id}`)
}

View File

@@ -0,0 +1,111 @@
import request from './request'
/** 客户档案 - 与 ERP 数据模型 SlClient 对齐 */
export interface Customer {
clientId?: number
clientCode?: string
clientName?: string
clientNick?: string
/** 兼容表单选择id = clientId */
id?: number
/** 兼容表单选择code = clientCode */
code?: string
/** 兼容表单选择name = clientName */
name?: string
/** 兼容表单选择contact = contact1 */
contact?: string
/** 兼容表单选择phone = contact1Tel */
phone?: string
clientEn?: string
clientDes?: string
clientLogo?: string
clientType?: string
clientLevel?: string
clientSource?: string
clientIndustry?: string
address?: string
website?: string
email?: string
tel?: string
contact1?: string
contact1Tel?: string
contact2?: string
contact2Tel?: string
creditCode?: string
bankName?: string
bankAccount?: string
taxNo?: string
invoiceAddress?: string
enableFlag?: 'Y' | 'N'
remark?: string
createBy?: string
createTime?: string
updateBy?: string
updateTime?: string
}
export interface CustomerQuery {
clientCode?: string
clientName?: string
clientNick?: string
/** 兼容:映射为 clientName */
name?: string
enableFlag?: 'Y' | 'N'
pageNum?: number
pageSize?: number
}
export interface CustomerListResponse {
list: Customer[]
total: number
}
const BASE = '/erp/sl/client'
function mapRow(r: any): Customer {
return {
...r,
id: r.clientId ?? r.id,
code: r.clientCode ?? r.code,
name: r.clientName ?? r.name,
contact: r.contact1 ?? r.contact,
phone: r.contact1Tel ?? r.phone
}
}
/** 获取客户列表(分页) */
export function getCustomerList(params: CustomerQuery): Promise<CustomerListResponse> {
const { name, ...rest } = params
const req = { ...rest, clientName: rest.clientName ?? name } as Record<string, unknown>
return request.get(`${BASE}/list`, { params: req }).then((res: any) => {
const rows = res.rows ?? res.data?.rows ?? res.list ?? []
const total = res.total ?? res.data?.total ?? 0
return { list: rows.map(mapRow), total }
})
}
/** 获取客户详情 */
export function getCustomerDetail(clientId: number): Promise<Customer> {
return request.get(`${BASE}/${clientId}`).then((res: any) => mapRow(res.data ?? res))
}
/** 新增客户 */
export function createCustomer(data: Partial<Customer>): Promise<void> {
return request.post(BASE, data)
}
/** 更新客户 */
export function updateCustomer(data: Partial<Customer>): Promise<void> {
return request.put(BASE, data)
}
/** 删除客户(支持单个或批量,逗号分隔 ID */
export function deleteCustomer(clientIds: number | number[]): Promise<void> {
const ids = Array.isArray(clientIds) ? clientIds.join(',') : String(clientIds)
return request.delete(`${BASE}/${ids}`)
}
/** 更新客户启用状态 */
export function updateCustomerStatus(clientId: number, enableFlag: 'Y' | 'N'): Promise<void> {
return request.put(BASE, { clientId, enableFlag })
}

View File

@@ -0,0 +1,108 @@
import request from './request'
export interface DeliverLine {
lineId?: number
id?: number
deliverId?: number
deliverCode?: string
orderLineId?: number
itemId?: number
itemCode?: string
materialCode?: string
itemName?: string
materialName?: string
specification?: string
spec?: string
unitOfMeasure?: string
unit?: string
orderQty?: number
deliverQty: number
remark?: string
}
export interface Deliver {
deliverId?: number
id?: number
deliverCode?: string
code?: string
clientId?: number
customerId?: number
clientCode?: string
customerCode?: string
clientName?: string
customerName?: string
deliverDate: string
status: string
totalQty?: number
deliveryAddress?: string
contact?: string
phone?: string
remark?: string
lines?: DeliverLine[]
createTime?: string
}
export interface DeliverQuery {
code?: string
customerName?: string
status?: string
page?: number
pageSize?: number
}
export interface DeliverListResponse {
list: Deliver[]
total: number
}
// 获取发货单列表
export function getDeliverList(params: DeliverQuery): Promise<DeliverListResponse> {
return request.get('/erp/sl/deliver/list', { params }).then((res: any) => {
return {
list: res.rows || [],
total: res.total || 0
}
})
}
// 获取发货单详情
export function getDeliverDetail(id: number): Promise<Deliver> {
return request.get(`/erp/sl/deliver/${id}`).then((res: any) => {
return res.data
})
}
// 新增发货单
export function createDeliver(data: Partial<Deliver>): Promise<void> {
return request.post('/erp/sl/deliver', data)
}
// 更新发货单
export function updateDeliver(id: number, data: Partial<Deliver>): Promise<void> {
return request.put('/erp/sl/deliver', { ...data, deliverId: id })
}
// 删除发货单
export function deleteDeliver(id: number): Promise<void> {
return request.delete(`/erp/sl/deliver/${id}`)
}
// 审核发货单
export function auditDeliver(id: number): Promise<void> {
return request.post(`/erp/sl/deliver/audit/${id}`)
}
// 反审核发货单
export function unauditDeliver(id: number): Promise<void> {
return request.post(`/erp/sl/deliver/unaudit/${id}`)
}
// 引入销售订单
export function getIntroduceOrderList(params: any): Promise<DeliverListResponse> {
return request.get('/erp/sl/deliver/introduce', { params }).then((res: any) => {
return {
list: res.rows || [],
total: res.total || 0
}
})
}

View File

@@ -0,0 +1,77 @@
import request from './request'
export interface Invoice {
invoiceId?: number
id?: number
invoiceCode?: string
code?: string
clientId?: number
customerId?: number
clientCode?: string
customerCode?: string
clientName?: string
customerName?: string
invoiceDate: string
invoiceType?: string
status: string
totalAmount?: number
taxAmount?: number
invoiceNo?: string
remark?: string
createTime?: string
}
export interface InvoiceQuery {
code?: string
customerName?: string
status?: string
page?: number
pageSize?: number
}
export interface InvoiceListResponse {
list: Invoice[]
total: number
}
// 获取销售发票列表
export function getInvoiceList(params: InvoiceQuery): Promise<InvoiceListResponse> {
return request.get('/erp/sl/invoice/list', { params }).then((res: any) => {
return {
list: res.rows || [],
total: res.total || 0
}
})
}
// 获取销售发票详情
export function getInvoiceDetail(id: number): Promise<Invoice> {
return request.get(`/erp/sl/invoice/${id}`).then((res: any) => {
return res.data
})
}
// 新增销售发票
export function createInvoice(data: Partial<Invoice>): Promise<void> {
return request.post('/erp/sl/invoice', data)
}
// 更新销售发票
export function updateInvoice(id: number, data: Partial<Invoice>): Promise<void> {
return request.put('/erp/sl/invoice', { ...data, invoiceId: id })
}
// 删除销售发票
export function deleteInvoice(id: number): Promise<void> {
return request.delete(`/erp/sl/invoice/${id}`)
}
// 审核销售发票
export function auditInvoice(id: number): Promise<void> {
return request.post(`/erp/sl/invoice/audit/${id}`)
}
// 反审核销售发票
export function unauditInvoice(id: number): Promise<void> {
return request.post(`/erp/sl/invoice/unaudit/${id}`)
}

View File

@@ -0,0 +1,201 @@
import request from '../request'
/** BOM 表头md_bom */
export interface BomHeader {
bomId?: number
bomCode?: string
bomName?: string
version?: string
versionDesc?: string
status?: string
itemId?: number
itemCode?: string
itemName?: string
itemSpec?: string
unitName?: string
baseQty?: number
enableFlag?: string
bomItemId?: number
bomItemCode?: string
bomItemName?: string
bomItemSpec?: string
unitOfMeasure?: string
itemOrProduct?: string
quantity?: number
lineNo?: number
lossRate?: number
supplyType?: string
tenantId?: string
remark?: string
createBy?: string
createTime?: string
updateBy?: string
updateTime?: string
}
/** BOM 明细md_product_bom */
export interface BomLine {
bomId?: number // 明细行ID现有表主键
bomCode?: string
bomName?: string
version?: string
versionDesc?: string
status?: string
itemId?: number // 母件物料ID
itemCode?: string
itemName?: string
itemSpec?: string
bomItemId?: number
bomItemCode?: string
bomItemName?: string
bomItemSpec?: string
unitOfMeasure?: string
unitName?: string
itemOrProduct?: string
quantity?: number
baseQty?: number
lineNo?: number
lossRate?: number
supplyType?: string
enableFlag?: string
tenantId?: string
delFlag?: string
remark?: string
createBy?: string
createTime?: string
updateBy?: string
updateTime?: string
/** 扩展字段(后端可忽略/不落库,页面需要透传) */
attr1?: string
attr2?: string
// 详情页表格里用到的前端临时字段(后端可忽略)
planRoute?: string
usageType?: string
drawingNo?: string
}
/** BOM 表头查询参数 */
export interface BomHeaderQuery {
bomCode?: string
bomName?: string
itemId?: number
itemCode?: string
itemName?: string
itemOrProduct?: string
itemTypeId?: number
status?: string
enableFlag?: string
pageNum?: number
pageSize?: number
}
/** BOM 表头列表响应 */
export interface BomHeaderListResponse {
rows: BomHeader[]
total: number
}
/** BOM 明细查询参数 */
export interface BomLineQuery {
bomCode?: string
itemId?: number
bomItemCode?: string
bomItemName?: string
status?: string
enableFlag?: string
pageNum?: number
pageSize?: number
}
/** BOM 明细列表响应 */
export interface BomLineListResponse {
rows: BomLine[]
total: number
}
const BOM_HEADER_BASE = '/mes/md/bom'
const BOM_LINE_BASE = '/mes/md/bom/line'
/** 查询BOM表头列表 */
export function listBomHeader(query?: BomHeaderQuery): Promise<BomHeaderListResponse> {
return request.get(`${BOM_HEADER_BASE}/list`, { params: query }).then((res: any) => ({
rows: res.rows || [],
total: res.total || 0
}))
}
/** 查询BOM表头详情 */
export function getBomHeader(bomId: number): Promise<{ data: BomHeader }> {
return request.get(`${BOM_HEADER_BASE}/${bomId}`)
}
/** 新增BOM表头 */
export function addBomHeader(data: Partial<BomHeader>): Promise<{ data: BomHeader }> {
return request.post(BOM_HEADER_BASE, data)
}
/** 修改BOM表头 */
export function updateBomHeader(data: Partial<BomHeader>): Promise<{ data: BomHeader }> {
return request.put(BOM_HEADER_BASE, data)
}
/** 删除BOM表头 */
export function delBomHeader(bomId: number | number[]): Promise<void> {
const ids = Array.isArray(bomId) ? bomId.join(',') : String(bomId)
return request.delete(`${BOM_HEADER_BASE}/${ids}`)
}
/** 查询BOM明细列表 */
export function listBomLine(query?: BomLineQuery): Promise<BomLineListResponse> {
return request.get(`${BOM_LINE_BASE}/list`, { params: query }).then((res: any) => ({
rows: res.rows || [],
total: res.total || 0
}))
}
/** 查询BOM明细详情 */
export function getBomLine(lineId: number): Promise<{ data: BomLine }> {
return request.get(`${BOM_LINE_BASE}/${lineId}`)
}
/** 新增BOM明细 */
export function addBomLine(data: Partial<BomLine>): Promise<{ data: BomLine }> {
return request.post(BOM_LINE_BASE, data)
}
/** 修改BOM明细 */
export function updateBomLine(data: Partial<BomLine>): Promise<{ data: BomLine }> {
return request.put(BOM_LINE_BASE, data)
}
/** 删除BOM明细 */
export function delBomLine(lineId: number | number[]): Promise<void> {
const ids = Array.isArray(lineId) ? lineId.join(',') : String(lineId)
return request.delete(`${BOM_LINE_BASE}/${ids}`)
}
// -----------------------------
// 兼容旧命名当前BOM页面仍在使用
// -----------------------------
export type ProductBom = BomHeader
export type ProductBomQuery = BomHeaderQuery
export type ProductBomListResponse = BomHeaderListResponse
export const listProductBom = listBomHeader
export const getProductBom = getBomHeader
export const addProductBom = addBomHeader
export const updateProductBom = updateBomHeader
export const delProductBom = delBomHeader
/** BOM状态选项 */
export const bomStatusOptions = [
{ value: 'DRAFT', label: '草稿' },
{ value: 'APPROVED', label: '已审核' },
{ value: 'OBSOLETE', label: '已废弃' }
]
/** 供应方式选项 */
export const supplyTypeOptions = [
{ value: 'PURCHASE', label: '采购' },
{ value: 'PRODUCE', label: '自制' },
{ value: 'OUTSOURCE', label: '委外' }
]

View File

@@ -0,0 +1,70 @@
import request from '../request'
export interface MdItem {
itemId?: number
itemCode?: string
itemName?: string
specification?: string
unitOfMeasure?: string
unitName?: string
itemTypeId?: number
itemTypeName?: string
itemOrProduct?: string
enableFlag?: string
safeStockFlag?: string
minStock?: number
maxStock?: number
batchFlag?: string
highValue?: string
remark?: string
createBy?: string
createTime?: string
updateBy?: string
updateTime?: string
}
export interface MdItemQuery {
itemCode?: string
itemName?: string
itemTypeId?: number
itemOrProduct?: string
enableFlag?: string
pageNum?: number
pageSize?: number
}
export interface MdItemListResponse {
rows: MdItem[]
total: number
}
const BASE = '/mes/md/mditem'
/** 查询物料列表 */
export function listMdItem(query?: MdItemQuery): Promise<MdItemListResponse> {
return request.get(`${BASE}/list`, { params: query }).then((res: any) => ({
rows: res.rows || [],
total: res.total || 0
}))
}
/** 查询物料详细 */
export function getMdItem(itemId: number): Promise<{ data: MdItem }> {
return request.get(`${BASE}/${itemId}`)
}
/** 新增物料 */
export function addMdItem(data: Partial<MdItem>): Promise<{ data: MdItem }> {
return request.post(BASE, data)
}
/** 修改物料 */
export function updateMdItem(data: Partial<MdItem>): Promise<{ data: MdItem }> {
return request.put(BASE, data)
}
/** 删除物料 */
export function delMdItem(itemId: number | number[]): Promise<void> {
const ids = Array.isArray(itemId) ? itemId.join(',') : String(itemId)
return request.delete(`${BASE}/${ids}`)
}

View File

@@ -0,0 +1,79 @@
import request from '../request'
export interface ItemType {
itemTypeId?: number
parentTypeId?: number
itemTypeCode?: string
itemTypeName?: string
orderNum?: number
enableFlag?: string
itemOrProduct?: string
remark?: string
createBy?: string
createTime?: string
updateBy?: string
updateTime?: string
children?: ItemType[]
}
export interface ItemTypeQuery {
itemTypeCode?: string
itemTypeName?: string
enableFlag?: string
}
const BASE = '/mes/md/itemtype'
/** 查询物料分类列表 */
export function listItemType(query?: ItemTypeQuery): Promise<{ data: ItemType[] }> {
return request.get(`${BASE}/list`, { params: query })
}
/** 查询物料分类下拉树结构 */
export function getItemTypeTreeselect(): Promise<{ data: any[] }> {
return request.get(`${BASE}/treeselect`)
}
/** 查询物料分类详细 */
export function getItemType(itemTypeId: number): Promise<{ data: ItemType }> {
return request.get(`${BASE}/${itemTypeId}`)
}
/** 新增物料分类 */
export function addItemType(data: Partial<ItemType>): Promise<void> {
return request.post(BASE, data)
}
/** 修改物料分类 */
export function updateItemType(data: Partial<ItemType>): Promise<void> {
return request.put(BASE, data)
}
/** 删除物料分类 */
export function delItemType(itemTypeId: number): Promise<void> {
return request.delete(`${BASE}/${itemTypeId}`)
}
/** 构建分类树 */
export function handleTree(data: ItemType[], idField = 'itemTypeId', parentField = 'parentTypeId'): ItemType[] {
const map = new Map<number, ItemType>()
const result: ItemType[] = []
data.forEach(item => {
map.set(item[idField as keyof ItemType] as number, { ...item, children: [] })
})
data.forEach(item => {
const current = map.get(item[idField as keyof ItemType] as number)!
const parentId = item[parentField as keyof ItemType] as number
if (parentId && map.has(parentId)) {
const parent = map.get(parentId)!
parent.children = parent.children || []
parent.children.push(current)
} else {
result.push(current)
}
})
return result
}

View File

@@ -0,0 +1,65 @@
import request from '../request'
export interface UnitMeasure {
measureId?: number
measureCode?: string
measureName?: string
primaryFlag?: string
primaryId?: number
changeRate?: number
enableFlag?: string
remark?: string
createBy?: string
createTime?: string
updateBy?: string
updateTime?: string
}
export interface UnitMeasureQuery {
measureCode?: string
measureName?: string
enableFlag?: string
pageNum?: number
pageSize?: number
}
export interface UnitMeasureListResponse {
rows: UnitMeasure[]
total: number
}
const BASE = '/mes/md/unitmeasure'
/** 查询计量单位列表 */
export function listUnitMeasure(query?: UnitMeasureQuery): Promise<UnitMeasureListResponse> {
return request.get(`${BASE}/list`, { params: query }).then((res: any) => ({
rows: res.rows || [],
total: res.total || 0
}))
}
/** 查询所有计量单位(不分页) */
export function listAllUnitMeasure(): Promise<{ data: UnitMeasure[] }> {
return request.get(`${BASE}/selectall`)
}
/** 查询计量单位详细 */
export function getUnitMeasure(measureId: number): Promise<{ data: UnitMeasure }> {
return request.get(`${BASE}/${measureId}`)
}
/** 新增计量单位 */
export function addUnitMeasure(data: Partial<UnitMeasure>): Promise<void> {
return request.post(BASE, data)
}
/** 修改计量单位 */
export function updateUnitMeasure(data: Partial<UnitMeasure>): Promise<void> {
return request.put(BASE, data)
}
/** 删除计量单位 */
export function delUnitMeasure(measureId: number | number[]): Promise<void> {
const ids = Array.isArray(measureId) ? measureId.join(',') : String(measureId)
return request.delete(`${BASE}/${ids}`)
}

View File

@@ -0,0 +1,64 @@
import request from '../request'
export interface Workshop {
workshopId?: number
workshopCode?: string
workshopName?: string
area?: string
charge?: string
enableFlag?: string
remark?: string
createBy?: string
createTime?: string
updateBy?: string
updateTime?: string
}
export interface WorkshopQuery {
workshopCode?: string
workshopName?: string
enableFlag?: string
pageNum?: number
pageSize?: number
}
export interface WorkshopListResponse {
rows: Workshop[]
total: number
}
const BASE = '/mes/md/workshop'
/** 查询车间列表 */
export function listWorkshop(query?: WorkshopQuery): Promise<WorkshopListResponse> {
return request.get(`${BASE}/list`, { params: query }).then((res: any) => ({
rows: res.rows || [],
total: res.total || 0
}))
}
/** 查询所有车间(不分页) */
export function listAllWorkshop(): Promise<{ data: Workshop[] }> {
return request.get(`${BASE}/listAll`)
}
/** 查询车间详细 */
export function getWorkshop(workshopId: number): Promise<{ data: Workshop }> {
return request.get(`${BASE}/${workshopId}`)
}
/** 新增车间 */
export function addWorkshop(data: Partial<Workshop>): Promise<void> {
return request.post(BASE, data)
}
/** 修改车间 */
export function updateWorkshop(data: Partial<Workshop>): Promise<void> {
return request.put(BASE, data)
}
/** 删除车间 */
export function delWorkshop(workshopId: number | number[]): Promise<void> {
const ids = Array.isArray(workshopId) ? workshopId.join(',') : String(workshopId)
return request.delete(`${BASE}/${ids}`)
}

View File

@@ -0,0 +1,68 @@
import request from '../request'
export interface Workstation {
workstationId?: number
workstationCode?: string
workstationName?: string
workstationAddress?: string
workshopId?: number
workshopName?: string
processId?: number
processName?: string
enableFlag?: string
remark?: string
createBy?: string
createTime?: string
updateBy?: string
updateTime?: string
}
export interface WorkstationQuery {
workstationCode?: string
workstationName?: string
workshopId?: number
enableFlag?: string
pageNum?: number
pageSize?: number
}
export interface WorkstationListResponse {
rows: Workstation[]
total: number
}
const BASE = '/mes/md/workstation'
/** 查询工作站列表 */
export function listWorkstation(query?: WorkstationQuery): Promise<WorkstationListResponse> {
return request.get(`${BASE}/list`, { params: query }).then((res: any) => ({
rows: res.rows || [],
total: res.total || 0
}))
}
/** 查询所有工作站(不分页) */
export function listAllWorkstation(): Promise<{ data: Workstation[] }> {
return request.get(`${BASE}/listAll`)
}
/** 查询工作站详细 */
export function getWorkstation(workstationId: number): Promise<{ data: Workstation }> {
return request.get(`${BASE}/${workstationId}`)
}
/** 新增工作站 */
export function addWorkstation(data: Partial<Workstation>): Promise<void> {
return request.post(BASE, data)
}
/** 修改工作站 */
export function updateWorkstation(data: Partial<Workstation>): Promise<void> {
return request.put(BASE, data)
}
/** 删除工作站 */
export function delWorkstation(workstationId: number | number[]): Promise<void> {
const ids = Array.isArray(workstationId) ? workstationId.join(',') : String(workstationId)
return request.delete(`${BASE}/${ids}`)
}

View File

@@ -0,0 +1,78 @@
import { listMdItem, getMdItem, type MdItem } from './masterdata/item'
export interface Material {
id: number
code: string
name: string
spec?: string
unit: string
category?: string
price?: number
status: number
}
export interface MaterialQuery {
code?: string
name?: string
category?: string
itemOrProduct?: string
page?: number
pageSize?: number
}
export interface MaterialListResponse {
list: Material[]
total: number
}
/** 将后端MdItem转换为前端Material */
function convertMdItemToMaterial(item: MdItem): Material {
return {
id: item.itemId || 0,
code: item.itemCode || '',
name: item.itemName || '',
spec: item.specification,
unit: item.unitOfMeasure || item.unitName || '',
category: item.itemTypeName,
price: 0, // 物料主数据中没有价格,价格在订单中设置
status: item.enableFlag === 'Y' ? 1 : 0
}
}
/** 获取物料列表 */
export async function getMaterialList(params: MaterialQuery): Promise<MaterialListResponse> {
try {
const query: any = {
itemCode: params.code,
itemName: params.name,
pageNum: params.page || 1,
pageSize: params.pageSize || 100
}
if (params.itemOrProduct) {
query.itemOrProduct = params.itemOrProduct
}
const res = await listMdItem(query)
// 返回所有物料,让用户自行选择
const list = res.rows.map(convertMdItemToMaterial)
return {
list,
total: res.total
}
} catch (error) {
console.error('获取物料列表失败:', error)
return { list: [], total: 0 }
}
}
/** 获取物料详情 */
export async function getMaterialDetail(id: number): Promise<Material> {
try {
const res = await getMdItem(id)
return convertMdItemToMaterial(res.data)
} catch (error) {
console.error('获取物料详情失败:', error)
throw error
}
}

View File

@@ -0,0 +1,142 @@
import request from './request'
export interface Mbom {
mbomId: number
mbomCode: string
mbomDate: string
status: string
businessType: string
issueStatus?: string
planId: number
planCode: string
salesOrderId?: number
salesOrderCode?: string
deliveryDate?: string
itemId: number
itemCode: string
itemName: string
unitName?: string
supplyType?: string
quantity: number
workshopId?: number
workshopName?: string
issueDate?: string
approverName?: string
approveDate?: string
remark?: string
createTime?: string
}
/** 物料清单明细行 */
export interface MbomLine {
lineId: number
mbomId: number
mbomCode?: string
lineNo?: number
bomLevel?: number
itemId: number
itemCode: string
itemName: string
specification?: string
unitName?: string
baseQty?: number
quantity: number
lossRate?: number
supplyType?: string
pickType?: string
remark?: string
}
/** 物料清单详情(表头 + 明细行) */
export interface MbomDetail extends Mbom {
lines?: MbomLine[]
}
export interface MbomQuery {
salesOrderCode?: string
mbomCode?: string
itemCode?: string
itemName?: string
beginDate?: string
endDate?: string
status?: string
supplyType?: string
pageNum?: number
pageSize?: number
}
export interface MbomListResponse {
rows: Mbom[]
total: number
}
// 获取物料清单列表
export function getMbomList(params: MbomQuery): Promise<MbomListResponse> {
return request.get('/erp/mp/mbom/list', { params }).then((res: any) => {
return {
rows: res.rows || [],
total: res.total || 0
}
})
}
// 获取物料清单详情(含明细行)
export function getMbomDetail(mbomId: number): Promise<MbomDetail> {
return request.get(`/erp/mp/mbom/${mbomId}`).then((res: any) => {
const data = res.data ?? res
return data as MbomDetail
})
}
// 获取物料清单明细列表
export function getMbomLines(mbomId: number): Promise<MbomLine[]> {
return request.get(`/erp/mp/mbomline/mbom/${mbomId}`).then((res: any) => {
const rows = res.rows ?? res.data ?? []
return rows as MbomLine[]
})
}
// 更新物料清单明细行
export function updateMbomLine(data: Partial<MbomLine>): Promise<void> {
return request.put('/erp/mp/mbomline', data)
}
// 新增物料清单
export function createMbom(data: Partial<Mbom>): Promise<void> {
return request.post('/erp/mp/mbom', data)
}
// 更新物料清单
export function updateMbom(data: Partial<Mbom>): Promise<void> {
return request.put('/erp/mp/mbom', data)
}
// 删除物料清单
export function deleteMbom(mbomIds: string): Promise<void> {
return request.delete(`/erp/mp/mbom/${mbomIds}`)
}
// 审核物料清单
export function approveMbom(mbomId: number): Promise<void> {
return request.put(`/erp/mp/mbom/approve/${mbomId}`)
}
// 反审核物料清单
export function unapproveMbom(mbomId: number): Promise<void> {
return request.put(`/erp/mp/mbom/unapprove/${mbomId}`)
}
// 下发车间
export function issueToWorkshop(mbomId: number, workshopId: number, workshopName: string): Promise<void> {
return request.put(`/erp/mp/mbom/issue/${mbomId}/${workshopId}/${workshopName}`)
}
// 撤销下发车间
export function revokeIssue(mbomId: number): Promise<void> {
return request.put(`/erp/mp/mbom/revoke-issue/${mbomId}`)
}
// BOM运算从生产计划
export function calcBom(planId: number): Promise<void> {
return request.put(`/erp/mp/plan/bom-calculate/${planId}`)
}

View File

@@ -0,0 +1,72 @@
import request from './request'
export interface PartsOrder {
partsId: number
partsCode: string
partsDate: string
status: string
itemId: number
itemCode: string
itemName: string
specification?: string
drawingNo?: string
unitName?: string
quantity: number
planQty?: number
completedQty?: number
remark?: string
createTime?: string
}
export interface PartsQuery {
partsCode?: string
itemCode?: string
itemName?: string
beginDate?: string
endDate?: string
status?: string
pageNum?: number
pageSize?: number
}
export interface PartsListResponse {
rows: PartsOrder[]
total: number
}
// 获取零部件订单列表
export function getPartsOrderList(params: PartsQuery): Promise<PartsListResponse> {
return request.get('/erp/mp/parts/list', { params }).then((res: any) => {
return {
rows: res.rows || [],
total: res.total || 0
}
})
}
// 获取零部件订单详情
export function getPartsOrderDetail(partsId: number): Promise<PartsOrder> {
return request.get(`/erp/mp/parts/${partsId}`).then((res: any) => {
return res.data
})
}
// 新增零部件订单
export function createPartsOrder(data: Partial<PartsOrder>): Promise<void> {
return request.post('/erp/mp/parts', data)
}
// 更新零部件订单
export function updatePartsOrder(data: Partial<PartsOrder>): Promise<void> {
return request.put('/erp/mp/parts', data)
}
// 删除零部件订单
export function deletePartsOrder(partsIds: string): Promise<void> {
return request.delete(`/erp/mp/parts/${partsIds}`)
}
// 审核零部件订单
export function approvePartsOrder(partsId: number): Promise<void> {
return request.put(`/erp/mp/parts/approve/${partsId}`)
}

View File

@@ -0,0 +1,357 @@
import request from './request'
// ============ 类型定义 ============
/** 生产计划明细行 */
export interface PlanLine {
lineId?: number
planId?: number
planCode?: string
lineNo?: number
salesLineId?: number
trackCode?: string
itemId?: number
itemCode?: string
itemName?: string
specification?: string
unitId?: number
unitName?: string
quantity?: number
qualityReq?: string
remark?: string
delFlag?: string
}
/** 生产计划单主表 */
export interface ProductionPlan {
planId?: number
planCode?: string
planDate?: string
status?: string
businessStatus?: string
businessType?: string
workType?: number
salesOrderId?: number
salesOrderCode?: string
salesUserId?: number
salesUserName?: string
deliveryDate?: string
bomId?: number
/** EBOM单号选择BOM后显示在表头订单BOM */
bomCode?: string
bomVersion?: string
bomDesc?: string
totalQuantity?: number
remark?: string
operatorId?: number
operatorName?: string
approverId?: number
approverName?: string
approveDate?: string
delFlag?: string
createBy?: string
createTime?: string
updateBy?: string
updateTime?: string
lines?: PlanLine[]
slaveList?: PlanLine[]
/** 部门名称(单据视图) */
deptName?: string
/** 操作员/业务人员(单据视图表头) */
operatorName?: string
/** 审核日期 */
approveDate?: string
/** 物料清单BOM运算结果详情页只读 */
mbomList?: MbomLine[]
/** 补料清单(详情页只读) */
supplementList?: SupplementLine[]
}
/** 明细视图数据(展开物料维度) */
export interface PlanDetailView {
lineId: number
planId: number
planCode: string
planDate: string
status: string
workType: number
salesOrderCode?: string
salesUserName?: string
deliveryDate?: string
trackCode?: string
itemId: number
itemCode: string
itemName: string
specification?: string
unitName?: string
quantity: number
/** 物料清单状态BOM运算 / BOM运算,BOM补料 / 空 */
mbomStatus?: string
}
/** 物料清单行BOM运算结果 */
export interface MbomLine {
mbomId?: number
mbomCode?: string
mbomStatus?: string
businessType?: string
issueStatus?: string
itemCode?: string
itemName?: string
unitName?: string
supplyType?: string
productionQty?: number
workshopId?: number
workshopName?: string
issueDate?: string
}
/** 补料清单行 */
export interface SupplementLine {
supCode?: string
supStatus?: string
businessType?: string
issueStatus?: string
itemCode?: string
itemName?: string
unitName?: string
supplyType?: string
productionQty?: number
supReason?: string
supDate?: string
remark?: string
}
/** 查询参数 */
export interface PlanQuery {
salesOrderCode?: string
planCode?: string
itemCode?: string
itemName?: string
beginDate?: string
endDate?: string
workType?: number
status?: string
businessStatus?: string
pageNum?: number
pageSize?: number
}
/** 分页响应 */
export interface PlanListResponse {
rows: ProductionPlan[]
total: number
}
export interface PlanDetailListResponse {
rows: PlanDetailView[]
total: number
}
/** 引入订单数据类型 */
export interface ImportOrder {
orderId: number
orderCode: string
orderDate: string
userId?: number
userName?: string
salesmanName?: string
clientName?: string
deliveryDate?: string
deliveryStatus?: string
businessType?: string
remark?: string
lines?: ImportOrderLine[]
}
/** 引入订单明细 */
export interface ImportOrderLine {
lineId: number
orderId: number
itemId: number
itemCode: string
itemName: string
specification?: string
unitOfMeasure?: string
quantity: number
qualityReq?: string
remark?: string
}
// ============ 状态映射 ============
export const PLAN_STATUS_MAP: Record<string, { label: string; type: string }> = {
'PREPARE': { label: '开立', type: 'info' },
'DRAFT': { label: '开立', type: 'info' },
'开立': { label: '开立', type: 'info' },
'APPROVED': { label: '审核', type: 'success' },
'审核': { label: '审核', type: 'success' },
'CLOSED': { label: '关闭', type: 'info' }
}
export const BUSINESS_STATUS_OPTIONS = [
{ value: 'NORMAL', label: '正常' },
{ value: 'PAUSE', label: '暂停' },
{ value: 'CANCEL', label: '取消' }
]
export const WORK_TYPE_OPTIONS = [
{ value: 0, label: '生产计划单' },
{ value: 1, label: '零部件计划单' },
{ value: 2, label: '零部件订单' }
]
// ============ API 接口 ============
const BASE = '/erp/mp/plan'
/** 获取生产计划单列表(单据视图) */
export function getProductionPlanList(params: PlanQuery): Promise<PlanListResponse> {
return request.get(`${BASE}/list`, { params }).then((res: any) => {
const rows = res.rows ?? res.data?.rows ?? []
const total = res.total ?? res.data?.total ?? 0
return { rows, total }
})
}
/** 获取生产计划单明细列表(明细视图,展开物料维度) */
export function getProductionPlanDetailList(params: PlanQuery): Promise<PlanDetailListResponse> {
return request.get(`${BASE}/lineList`, { params }).then((res: any) => {
const rows = res.rows ?? res.data?.rows ?? []
const total = res.total ?? res.data?.total ?? 0
return { rows, total }
})
}
/** 获取生产计划单详情(含明细行) */
export function getProductionPlanDetail(planId: number): Promise<ProductionPlan> {
return request.get(`${BASE}/${planId}`).then((res: any) => {
const data = res.data ?? res
// 统一明细字段名
if (data.slaveList && !data.lines) {
data.lines = data.slaveList
}
return data
})
}
/** 新增生产计划单 */
export function createProductionPlan(data: Partial<ProductionPlan>): Promise<{ planId: number }> {
const payload = { ...data }
if (payload.lines) {
payload.slaveList = payload.lines
delete payload.lines
}
return request.post(BASE, payload).then((res: any) => res.data ?? res)
}
/** 更新生产计划单 */
export function updateProductionPlan(data: Partial<ProductionPlan>): Promise<void> {
const payload = { ...data }
if (payload.lines) {
payload.slaveList = payload.lines
delete payload.lines
}
return request.put(BASE, payload)
}
/** 删除生产计划单(支持批量) */
export function deleteProductionPlan(planIds: number | number[] | string): Promise<void> {
const ids = Array.isArray(planIds) ? planIds.join(',') : String(planIds)
return request.delete(`${BASE}/${ids}`)
}
/** 审核生产计划单(支持批量) */
export function approveProductionPlan(planIds: number | number[]): Promise<void> {
const ids = Array.isArray(planIds) ? planIds.join(',') : String(planIds)
return request.put(`${BASE}/approve/${ids}`)
}
/** 反审核生产计划单(支持批量) */
export function unapproveProductionPlan(planIds: number | number[]): Promise<void> {
const ids = Array.isArray(planIds) ? planIds.join(',') : String(planIds)
return request.put(`${BASE}/reject/${ids}`)
}
/** 导出生产计划单 */
export function exportProductionPlan(params: PlanQuery): Promise<Blob> {
return request.get(`${BASE}/export`, {
params,
responseType: 'blob'
})
}
/** BOM运算 */
export function bomCalculate(planId: number): Promise<void> {
return request.post(`/erp/mp/mbom/calc`, { planId })
}
// ============ 引入订单相关 ============
/** 获取可引入的销售订单列表(已审核的订单) */
export function getImportOrderList(params?: {
orderCode?: string
itemCode?: string
itemName?: string
beginDate?: string
endDate?: string
}): Promise<ImportOrder[]> {
return request.get('/erp/sl/order/list', {
params: {
...params,
orderStatus: '审核',
pageNum: 1,
pageSize: 100
}
}).then((res: any) => {
const rows = res.rows ?? res.data?.rows ?? []
// 转换字段名
return rows.map((row: any) => ({
orderId: row.orderId,
orderCode: row.orderCode,
orderDate: row.orderDate,
userId: row.salesmanId,
userName: row.salesmanName,
salesmanName: row.salesmanName,
clientName: row.clientName,
deliveryDate: row.deliveryDate,
deliveryStatus: row.deliveryDate && new Date(row.deliveryDate) < new Date() ? '超期' : '预计',
businessType: '销售订单',
remark: row.remark
}))
})
}
/** 获取销售订单详情(用于引入订单明细) */
export function getImportOrderDetail(orderId: number): Promise<ImportOrder> {
return request.get(`/erp/sl/order/${orderId}`).then((res: any) => {
const data = res.data ?? res
const lines = data.lines ?? data.slaveList ?? []
const salesPersonName = data.salesmanName ?? data.salesUserName ?? ''
return {
orderId: data.orderId,
orderCode: data.orderCode,
orderDate: data.orderDate,
userId: data.salesmanId ?? data.salesUserId,
userName: salesPersonName,
salesmanName: salesPersonName,
clientName: data.clientName,
deliveryDate: data.deliveryDate,
deliveryStatus: data.deliveryDate && new Date(data.deliveryDate) < new Date() ? '超期' : '预计',
businessType: '销售订单',
remark: data.remark,
lines: lines.map((line: any) => ({
lineId: line.lineId,
orderId: line.orderId,
itemId: line.itemId,
itemCode: line.itemCode,
itemName: line.itemName,
specification: line.specification,
unitOfMeasure: line.unitOfMeasure,
quantity: line.quantity,
qualityReq: line.qualityReq,
remark: line.remark
}))
}
})
}

View File

@@ -0,0 +1,70 @@
import request from './request'
export interface PurchaseInvoice {
invoiceId: number
invoiceCode: string
invoiceDate: string
status: string
financeStatus: string
businessType: string
supplierId: number
supplierName: string
invoiceNo?: string
invoiceAmount: number
taxRate?: number
taxAmount?: number
totalAmount?: number
remark?: string
operatorName?: string
approverName?: string
approveDate?: string
createTime?: string
}
export interface PurchaseInvoiceQuery {
invoiceCode?: string
supplierName?: string
invoiceNo?: string
beginDate?: string
endDate?: string
status?: string
pageNum?: number
pageSize?: number
}
export interface PurchaseInvoiceListResponse {
rows: PurchaseInvoice[]
total: number
}
// 获取采购发票列表
export function getPurchaseInvoiceList(params: PurchaseInvoiceQuery): Promise<PurchaseInvoiceListResponse> {
return request.get('/erp/po/invoice/list', { params }).then((res: any) => {
return {
rows: res.rows || [],
total: res.total || 0
}
})
}
// 获取采购发票详情
export function getPurchaseInvoiceDetail(invoiceId: number): Promise<PurchaseInvoice> {
return request.get(`/erp/po/invoice/${invoiceId}`).then((res: any) => {
return res.data
})
}
// 新增采购发票
export function createPurchaseInvoice(data: Partial<PurchaseInvoice>): Promise<void> {
return request.post('/erp/po/invoice', data)
}
// 更新采购发票
export function updatePurchaseInvoice(data: Partial<PurchaseInvoice>): Promise<void> {
return request.put('/erp/po/invoice', data)
}
// 删除采购发票
export function deletePurchaseInvoice(invoiceIds: string): Promise<void> {
return request.delete(`/erp/po/invoice/${invoiceIds}`)
}

View File

@@ -0,0 +1,60 @@
import request from './request'
export interface PurchaseNeedRow {
purchaseId: number
salesOrderCode: string
planCode: string
purchaseCode: string
itemCode: string
itemName: string
demandQty: number
availableQty: number
purchaseQty: number
orderedQty: number
unorderedQty: number // = purchaseQty - orderedQty (backend returns in totalQuantity)
purchaseDate: string
remark?: string
}
export interface PurchaseNeedQuery {
salesOrderCode?: string
itemCode?: string
itemName?: string
businessType?: string
beginDate?: string
endDate?: string
pageNum?: number
pageSize?: number
}
export interface PurchaseNeedListResponse {
rows: PurchaseNeedRow[]
total: number
}
export interface PurchaseNeedSummary {
totalPurchaseQty: number
totalOrderedQty: number
totalUnorderedQty: number
}
// 查询采购计划需求列表
export function getPurchaseNeedList(params: PurchaseNeedQuery): Promise<PurchaseNeedListResponse> {
return request.get('/erp/mp/purchase/need/list', { params }).then((res: any) => {
const rows = (res.rows || []).map((r: any) => ({
...r,
unorderedQty: r.totalQuantity // backend puts unordered qty in totalQuantity field
}))
return { rows, total: res.total || 0 }
})
}
// 查询采购计划需求汇总
export function getPurchaseNeedSummary(params: PurchaseNeedQuery): Promise<PurchaseNeedSummary> {
return request.get('/erp/mp/purchase/need/summary', { params }).then((res: any) => res.data || {})
}
// 导出采购计划需求表
export function exportPurchaseNeed(params: PurchaseNeedQuery): Promise<Blob> {
return request.post('/erp/mp/purchase/need/export', params, { responseType: 'blob' })
}

View File

@@ -0,0 +1,237 @@
import request from './request'
export interface PurchaseOrderLine {
lineId: number
orderId: number
orderCode: string
lineNo: number
trackCode?: string
planCode?: string
itemId: number
itemCode: string
itemName: string
specification?: string
unitName?: string
needDate?: string
quantity: number
unitPrice?: number
amount?: number
arrivedQuantity?: number
remark?: string
}
export interface PurchaseOrder {
orderId: number
orderCode: string
orderDate: string
status: string
businessStatus?: string
businessType: string
orderType: string
materialNeed: string
supplierId?: number
supplierCode?: string
supplierName?: string
deptId?: number
deptName?: string
userId?: number
userName?: string
deliveryDate?: string
contractNo?: string
contractFile?: string
totalQuantity?: number
totalAmount?: number
arrivedQuantity?: number
remark?: string
operatorId?: number
operatorName?: string
approverId?: number
approverName?: string
approveDate?: string
lines: PurchaseOrderLine[]
createTime?: string
// Detail-view join fields
trackCode?: string
planCode?: string
itemCode?: string
itemName?: string
needDate?: string
quantity?: number
lineArrivedQuantity?: number
}
/** 供应商采购订单用数据来源md_vendor */
export interface PoSupplier {
supplierId: number
supplierCode?: string
supplierName: string
supplierNick?: string
tel?: string
contact1?: string
contact1Tel?: string
enableFlag?: string
}
/** 引入弹窗行(采购计划明细) */
export interface LeadInRow {
purchaseId: number
purchaseCode: string
salesOrderCode?: string
salesUserName?: string
deliveryDate?: string
itemId: number
itemCode: string
itemName: string
specification?: string
unitName?: string
demandDate?: string
purchaseQty: number
orderedQty: number
unpurchasedQty?: number
}
export interface PurchaseOrderQuery {
trackCode?: string
orderCode?: string
supplierName?: string
itemCode?: string
itemName?: string
beginDate?: string
endDate?: string
status?: string
pageNum?: number
pageSize?: number
}
export interface PurchaseOrderListResponse {
rows: PurchaseOrder[]
total: number
}
// 获取采购订单列表
export function getPurchaseOrderList(params: PurchaseOrderQuery): Promise<PurchaseOrderListResponse> {
return request.get('/erp/po/order/list', { params }).then((res: any) => {
return {
rows: res.rows || [],
total: res.total || 0
}
})
}
// 获取采购订单详情
export function getPurchaseOrderDetail(orderId: number): Promise<PurchaseOrder> {
return request.get(`/erp/po/order/${orderId}`).then((res: any) => {
return res.data
})
}
// 新增采购订单
export function createPurchaseOrder(data: Partial<PurchaseOrder>): Promise<void> {
return request.post('/erp/po/order', data)
}
// 更新采购订单
export function updatePurchaseOrder(data: Partial<PurchaseOrder>): Promise<void> {
return request.put('/erp/po/order', data)
}
// 删除采购订单
export function deletePurchaseOrder(orderIds: string): Promise<void> {
return request.delete(`/erp/po/order/${orderIds}`)
}
// 获取采购订单单据视图列表
export function getPurchaseOrderDocList(params: PurchaseOrderQuery): Promise<PurchaseOrderListResponse> {
return request.get('/erp/po/order/docList', { params }).then((res: any) => ({
rows: res.rows || [],
total: res.total || 0
}))
}
// 获取采购订单汇总
export function getPurchaseOrderSummary(params: PurchaseOrderQuery): Promise<{ totalOrderQty: number; totalArrivedQty: number }> {
return request.get('/erp/po/order/summary', { params }).then((res: any) => res.data || {})
}
// 生成采购订单编码(后端返回的编码在 data 中msg 为「操作成功」)
export function genPurchaseOrderCode(): Promise<string> {
return request.get('/erp/po/order/genCode').then((res: any) => res.data ?? res.msg ?? '')
}
// 审核采购订单
export function approvePurchaseOrder(orderIds: string): Promise<void> {
return request.put(`/erp/po/order/approve/${orderIds}`)
}
// 反审核采购订单
export function unapprovePurchaseOrder(orderIds: string): Promise<void> {
return request.put(`/erp/po/order/unapprove/${orderIds}`)
}
// 导出采购订单
export function exportPurchaseOrder(params: PurchaseOrderQuery): Promise<Blob> {
return request.post('/erp/po/order/export', params, { responseType: 'blob' })
}
// ============ 供应商 API使用 MOM md_vendor表 erp_po_supplier 在 my_mes 中未建) ============
export function getPoSupplierList(params?: { supplierName?: string; contact1?: string; pageNum?: number; pageSize?: number }): Promise<{ rows: PoSupplier[]; total: number }> {
const { supplierName, contact1, pageNum = 1, pageSize = 200, ...rest } = params ?? {}
return request.get('/mes/md/vendor/list', {
params: { enableFlag: 'Y', pageNum, pageSize, vendorName: supplierName, contact1, ...rest }
}).then((res: any) => {
const rows = (res.rows ?? []).map((v: any) => ({
supplierId: v.vendorId,
supplierCode: v.vendorCode,
supplierName: v.vendorName ?? '',
supplierNick: v.vendorNick,
tel: v.tel,
contact1: v.contact1,
contact1Tel: v.contact1Tel,
enableFlag: v.enableFlag
}))
return { rows, total: res.total ?? 0 }
})
}
// ============ 引入采购计划单明细 API ============
export function getLeadInList(params?: { salesOrderCode?: string; itemCode?: string; itemName?: string; businessType?: string; pageNum?: number; pageSize?: number }): Promise<{ rows: LeadInRow[]; total: number }> {
return request.get('/erp/po/order/leadIn', { params: { pageNum: 1, pageSize: 200, ...params } }).then((res: any) => {
const rows = (res.rows ?? []).map((r: any) => ({
...r,
unpurchasedQty: (r.purchaseQty ?? 0) - (r.orderedQty ?? 0)
}))
return { rows, total: res.total ?? 0 }
})
}
// ============ 状态映射 ============
export const STATUS_MAP: Record<string, { label: string; type: string }> = {
PREPARE: { label: '开立', type: 'info' },
DRAFT: { label: '开立', type: 'info' },
APPROVED: { label: '审核', type: 'success' },
CLOSED: { label: '关闭', type: '' },
REJECTED: { label: '退回', type: 'warning' }
}
export const BUSINESS_STATUS_MAP: Record<string, string> = {
NORMAL: '正常', COMPLETED: '完成', PAUSE: '暂停', CANCEL: '取消'
}
export const BUSINESS_TYPE_OPTIONS = [
{ value: '原材料', label: '原材料' },
{ value: '零部件', label: '零部件' },
{ value: '装配件', label: '装配件' },
{ value: '成品', label: '成品' },
{ value: '五金件', label: '五金件' },
{ value: '包装物', label: '包装物' }
]
export const BUSINESS_STATUS_OPTIONS = [
{ value: 'NORMAL', label: '正常' },
{ value: 'COMPLETED', label: '完成' },
{ value: 'PAUSE', label: '暂停' },
{ value: 'CANCEL', label: '取消' }
]

View File

@@ -0,0 +1,344 @@
import request from './request'
// ============ Type Definitions ============
/** Purchase plan line item */
export interface PurchasePlanLine {
purchaseId?: number
purchaseCode?: string
lineNo?: number
itemId?: number
itemCode: string
itemName: string
specification?: string
unitName?: string
demandDate?: string
demandQty?: number
availableQty?: number
purchaseQty: number
orderedQty?: number
remark?: string
}
/** Purchase plan flat row (detail view) */
export interface PurchasePlan {
purchaseId: number
purchaseCode: string
purchaseDate: string
status: string
needType: number
businessType?: string
businessStatus?: string
planId?: number
planCode?: string
salesOrderId?: number
salesOrderCode?: string
salesUserName?: string
deliveryDate?: string
itemId?: number
itemCode?: string
itemName?: string
specification?: string
unitName?: string
totalQuantity?: number
demandQty?: number
availableQty?: number
purchaseQty: number
orderedQty?: number
remark?: string
deptId?: number
deptName?: string
operatorId?: number
operatorName?: string
operatorName2?: string
approverId?: number
approverName?: string
approveDate?: string
createTime?: string
}
/** Purchase plan detail (header + lines from /detail/{id} endpoint) */
export interface PurchasePlanDetail {
purchaseId?: number
purchaseCode: string
purchaseDate: string
status: string
businessType?: string
businessStatus?: string
needType: number
planId?: number
planCode?: string
salesOrderId?: number
salesOrderCode?: string
salesUserName?: string
deliveryDate?: string
headerItemCode?: string
headerItemName?: string
unitName?: string
totalQuantity?: number
deptId?: number
deptName?: string
operatorId?: number
operatorName?: string
operatorName2?: string
approverId?: number
approverName?: string
approveDate?: string
remark?: string
lines: PurchasePlanLine[]
}
/** List query params */
export interface PurchasePlanQuery {
salesOrderCode?: string
purchaseCode?: string
itemCode?: string
itemName?: string
needType?: number
status?: string
businessStatus?: string
'params[beginDate]'?: string
'params[endDate]'?: string
'params[itemTypeId]'?: number | string
pageNum?: number
pageSize?: number
}
/** Summary response */
export interface PurchasePlanSummary {
totalPurchaseQty: number
totalOrderedQty: number
}
/** Import dialog - production plan parent row */
export interface ImportPlanRow {
planId: number
planCode: string
salesOrderCode?: string
salesUserName?: string
deliveryDate?: string
itemCode?: string
itemName?: string
unitName?: string
quantity?: number
children?: ImportPlanMaterial[]
}
/** Import dialog - material detail child row */
export interface ImportPlanMaterial {
mbomId?: number
/** Stable unique key for table row-key (mbomId or composite fallback) */
materialKey?: string
planId?: number
planCode?: string
salesOrderCode?: string
salesUserName?: string
deliveryDate?: string
itemId?: number
itemCode: string
itemName: string
specification?: string
unitName?: string
demandQty: number
availableQty?: number
purchasedQty?: number
unpurchasedQty?: number
remark?: string
}
// ============ Status Maps ============
export const STATUS_MAP: Record<string, { label: string; type: string }> = {
'PREPARE': { label: '开立', type: 'info' },
'DRAFT': { label: '开立', type: 'info' },
'APPROVED': { label: '审核', type: 'success' },
'REJECTED': { label: '退回', type: 'warning' }
}
export const STATUS_OPTIONS = [
{ value: 'PREPARE', label: '开立' },
{ value: 'APPROVED', label: '审核' },
{ value: 'REJECTED', label: '退回' }
]
export const BUSINESS_STATUS_OPTIONS = [
{ value: 'NORMAL', label: '正常' },
{ value: 'PAUSE', label: '暂停' },
{ value: 'CANCEL', label: '取消' },
{ value: 'COMPLETED', label: '完成' }
]
export const BUSINESS_STATUS_MAP: Record<string, string> = {
'NORMAL': '正常',
'PAUSE': '暂停',
'CANCEL': '取消',
'COMPLETED': '完成'
}
export const BUSINESS_TYPE_OPTIONS = [
{ value: '原材料', label: '原材料' },
{ value: '零部件', label: '零部件' },
{ value: '装配件', label: '装配件' },
{ value: '成品', label: '成品' },
{ value: '五金件', label: '五金件' },
{ value: '包装物', label: '包装物' }
]
export const NEED_TYPE_OPTIONS = [
{ value: 0, label: '订单用料' },
{ value: 1, label: '库存备料' }
]
export function isEditableStatus(status: string): boolean {
return status === 'PREPARE' || status === 'DRAFT' || status === 'REJECTED'
}
export function isApprovedStatus(status: string): boolean {
return status === 'APPROVED'
}
// ============ API Functions ============
const BASE = '/erp/mp/purchase'
export function getPurchasePlanList(params: PurchasePlanQuery) {
return request.get<any>(`${BASE}/list`, { params }).then((res: any) => ({
rows: (res.rows ?? []) as PurchasePlan[],
total: (res.total ?? 0) as number
}))
}
export function getPurchasePlanDocList(params: PurchasePlanQuery) {
return request.get<any>(`${BASE}/docList`, { params }).then((res: any) => ({
rows: (res.rows ?? []) as PurchasePlan[],
total: (res.total ?? 0) as number
}))
}
export function getPurchasePlanSummary(params: PurchasePlanQuery) {
return request.get<any>(`${BASE}/summary`, { params }).then((res: any) => {
const d = res.data ?? res
return { totalPurchaseQty: d.totalPurchaseQty ?? 0, totalOrderedQty: d.totalOrderedQty ?? 0 } as PurchasePlanSummary
})
}
export function getPurchasePlanDetail(idOrCode: number | string) {
return request.get<any>(`${BASE}/detail/${idOrCode}`).then((res: any) => {
const d = res.data ?? res
if (!d.lines) d.lines = d.slaveList ?? d.details ?? []
return d as PurchasePlanDetail
})
}
export function getPurchasePlanById(purchaseId: number) {
return request.get<any>(`${BASE}/${purchaseId}`).then((res: any) => (res.data ?? res) as PurchasePlan)
}
export function createPurchasePlan(data: Partial<PurchasePlanDetail>) {
return request.post<any>(BASE, data).then((res: any) => res.data ?? res)
}
export function updatePurchasePlan(data: Partial<PurchasePlanDetail>) {
return request.put<any>(BASE, data)
}
export function deletePurchasePlan(purchaseIds: string) {
return request.delete<any>(`${BASE}/${purchaseIds}`)
}
export function deletePurchasePlanByCode(purchaseCode: string) {
return request.delete<any>(`${BASE}/byCode/${purchaseCode}`)
}
export function approvePurchasePlan(purchaseIds: string | number) {
return request.put<any>(`${BASE}/approve/${purchaseIds}`)
}
export function unapprovePurchasePlan(purchaseIds: string | number) {
return request.put<any>(`${BASE}/unapprove/${purchaseIds}`)
}
export function genPurchaseCode() {
return request.get<any>(`${BASE}/genCode`).then((res: any) => (res.data ?? res.msg ?? '') as string)
}
export function exportPurchasePlan(params: PurchasePlanQuery) {
return request.post<any>(`${BASE}/export`, params, { responseType: 'blob' })
}
export function generateFromMbom(mbomId: number) {
return request.post<any>(`${BASE}/generate/${mbomId}`)
}
// ============ Import Dialog APIs ============
export function getImportPlanList(params?: {
salesOrderCode?: string
itemCode?: string
itemName?: string
beginDate?: string
endDate?: string
}) {
const q: any = { status: 'APPROVED', pageNum: 1, pageSize: 200 }
if (params?.salesOrderCode) q.salesOrderCode = params.salesOrderCode
if (params?.itemCode) q.itemCode = params.itemCode
if (params?.itemName) q.itemName = params.itemName
if (params?.beginDate) q['params[beginDate]'] = params.beginDate
if (params?.endDate) q['params[endDate]'] = params.endDate
return request.get<any>('/erp/mp/plan/list', { params: q }).then((res: any) => {
const rows = res.rows ?? res.data?.rows ?? []
return rows.map((row: any) => ({
planId: row.planId,
planCode: row.planCode,
salesOrderCode: row.salesOrderCode,
salesUserName: row.salesUserName,
deliveryDate: row.deliveryDate,
itemCode: row.itemCode,
itemName: row.itemName,
unitName: row.unitName,
quantity: row.totalQuantity ?? row.quantity,
children: []
})) as ImportPlanRow[]
})
}
export function getImportPlanMaterials(planId: number) {
// 查询该生产计划下的MBOM明细行子件物料不再过滤supplyType以展示所有物料
return request.get<any>(`/erp/mp/mbomline/plan/${planId}`).then((res: any) => {
const rows = res.data ?? res.rows ?? []
return rows.map((row: any, index: number) => {
const lineId = row.lineId ?? row.mbomId
const materialKey =
lineId != null ? String(lineId) : `plan_${planId}_${row.itemId ?? row.itemCode ?? index}_${index}`
const demandQty = row.quantity ?? 0
const purchasedQty = row.purchasedQty ?? row.orderedQty ?? 0
return {
mbomId: lineId,
materialKey,
planId,
planCode: row.planCode ?? row.mbomCode,
itemId: row.itemId,
itemCode: row.itemCode,
itemName: row.itemName,
specification: row.specification,
unitName: row.unitName,
demandQty,
availableQty: row.availableQty ?? row.stockQty ?? 0,
purchasedQty,
unpurchasedQty: row.unpurchasedQty ?? (demandQty - purchasedQty),
remark: row.remark ?? ''
}
}) as ImportPlanMaterial[]
})
}
export function getItemTypeList() {
return request.get<any>('/mes/md/itemtype/list', { params: { pageNum: 1, pageSize: 100 } }).then((res: any) => {
const rows = res.rows ?? res.data?.rows ?? (Array.isArray(res.data) ? res.data : [])
return rows.map((row: any) => ({
itemTypeId: row.itemTypeId,
itemTypeName: row.itemTypeName
})) as Array<{ itemTypeId: number; itemTypeName: string }>
})
}

View File

@@ -0,0 +1,227 @@
import request from '../request'
// ==================== 类型定义 ====================
/** EBOM 表头 */
export interface EbomHeader {
bomId?: number
bomCode?: string
bomName?: string
bomDate?: string
version?: string
versionDesc?: string
status?: string
businessType?: string
businessStatus?: string
drawingNo?: string
itemId?: number
itemCode?: string
itemName?: string
itemSpec?: string
unitName?: string
baseQty?: number
operatorId?: number
operatorName?: string
deptId?: number
deptName?: string
approverId?: number
approverName?: string
approveDate?: string
enableFlag?: string
remark?: string
tenantId?: string
delFlag?: string
createBy?: string
createTime?: string
updateBy?: string
updateTime?: string
/** 明细行 (表单提交时携带) */
lines?: EbomLine[]
}
/** EBOM 明细行 */
export interface EbomLine {
lineId?: number
bomId?: number
bomCode?: string
lineNo?: number
bomItemId?: number
bomItemCode?: string
bomItemName?: string
bomItemSpec?: string
unitOfMeasure?: string
unitName?: string
itemOrProduct?: string
quantity?: number
numerator?: number
denominator?: number
lossRate?: number
supplyType?: string
pickType?: string
usageType?: string
routeId?: number
routeName?: string
drawingNo?: string
remark?: string
tenantId?: string
delFlag?: string
/** 前端临时字段 */
_isNew?: boolean
}
/** 查询参数 */
export interface EbomQuery {
bomCode?: string
itemCode?: string
itemName?: string
itemTypeId?: number
status?: string
businessStatus?: string
beginDate?: string
endDate?: string
workType?: number
pageNum?: number
pageSize?: number
}
/** 列表响应 */
export interface EbomListResponse {
rows: EbomHeader[]
total: number
}
// ==================== 常量定义 ====================
/** 单据状态映射 */
export const STATUS_MAP: Record<string, { label: string; type: string }> = {
DRAFT: { label: '开立', type: 'info' },
APPROVED: { label: '审核', type: 'success' },
REJECTED: { label: '退回', type: 'warning' }
}
/** 单据状态选项 */
export const STATUS_OPTIONS = [
{ value: 'DRAFT', label: '开立' },
{ value: 'APPROVED', label: '审核' },
{ value: 'REJECTED', label: '退回' }
]
/** 业务状态选项 */
export const BIZ_STATUS_OPTIONS = [
{ value: 'NORMAL', label: '正常' },
{ value: 'PAUSE', label: '暂停' },
{ value: 'CANCEL', label: '取消' }
]
/** 业务类型选项 */
export const BIZ_TYPE_OPTIONS = [
{ value: 'MECHANICAL', label: '机械BOM' },
{ value: 'ELECTRICAL', label: '电气BOM' },
{ value: 'ASSEMBLY', label: '装配BOM' },
{ value: 'GENERAL', label: '通用BOM' }
]
/** 领料方式选项 */
export const PICK_TYPE_OPTIONS = [
{ value: 'ORDER', label: '按单领用' },
{ value: 'DIRECT', label: '直接领用' }
]
/** 用量方式选项 */
export const USAGE_TYPE_OPTIONS = [
{ value: 'RATIO', label: '按比例' },
{ value: 'FIXED', label: '固定用量' }
]
/** 供应方式选项 */
export const SUPPLY_TYPE_OPTIONS = [
{ value: 'PURCHASE', label: '采购' },
{ value: 'PRODUCE', label: '生产' },
{ value: 'OUTSOURCE', label: '委外' },
{ value: 'ASSEMBLY', label: '装配' },
{ value: 'PROCESS', label: '加工' }
]
// ==================== API 函数 ====================
const BASE = '/mes/md/bom'
const LINE_BASE = '/mes/md/bom/line'
/** 查询EBOM列表单据视图 */
export function listEbom(query?: EbomQuery): Promise<EbomListResponse> {
return request.get(`${BASE}/list`, { params: query }).then((res: any) => ({
rows: res.rows || [],
total: res.total || 0
}))
}
/** 查询EBOM列表明细视图 - 含物料信息的展开列表) */
export function listEbomDetail(query?: EbomQuery): Promise<EbomListResponse> {
return request.get(`${BASE}/list`, { params: query }).then((res: any) => ({
rows: res.rows || [],
total: res.total || 0
}))
}
/** 获取EBOM详情 */
export function getEbom(bomId: number): Promise<{ data: EbomHeader }> {
return request.get(`${BASE}/${bomId}`)
}
/** 新增EBOM */
export function addEbom(data: Partial<EbomHeader>): Promise<{ data: EbomHeader }> {
return request.post(BASE, data)
}
/** 修改EBOM */
export function updateEbom(data: Partial<EbomHeader>): Promise<{ data: EbomHeader }> {
return request.put(BASE, data)
}
/** 删除EBOM */
export function deleteEbom(ids: number | number[]): Promise<void> {
const idStr = Array.isArray(ids) ? ids.join(',') : String(ids)
return request.delete(`${BASE}/${idStr}`)
}
/** 审核EBOM */
export function approveEbom(bomId: number): Promise<void> {
return request.put(`${BASE}/approve`, { bomId })
}
/** 反审核EBOM */
export function unapproveEbom(bomId: number): Promise<void> {
return request.put(`${BASE}/reject`, { bomId })
}
/** 查询BOM明细列表 */
export function listEbomLines(query?: { bomCode?: string; pageNum?: number; pageSize?: number }): Promise<{ rows: EbomLine[]; total: number }> {
return request.get(`${LINE_BASE}/list`, { params: query }).then((res: any) => ({
rows: res.rows || [],
total: res.total || 0
}))
}
/** 新增BOM明细 */
export function addEbomLine(data: Partial<EbomLine>): Promise<{ data: EbomLine }> {
return request.post(LINE_BASE, data)
}
/** 修改BOM明细 */
export function updateEbomLine(data: Partial<EbomLine>): Promise<{ data: EbomLine }> {
return request.put(LINE_BASE, data)
}
/** 删除BOM明细 */
export function deleteEbomLine(ids: number | number[]): Promise<void> {
const idStr = Array.isArray(ids) ? ids.join(',') : String(ids)
return request.delete(`${LINE_BASE}/${idStr}`)
}
/** 导出EBOM列表GET后端与 POST /export 行为一致) */
export function exportEbom(query?: EbomQuery): Promise<Blob> {
return request.get(`${BASE}/export`, {
params: query,
responseType: 'blob'
})
}

View File

@@ -0,0 +1,91 @@
import request from './request'
export interface RejectLine {
lineId: number
rejectId: number
rejectCode: string
lineNo: number
checkinLineId?: number
trackCode?: string
itemId: number
itemCode: string
itemName: string
specification?: string
unitName?: string
quantity: number
outQuantity?: number
returnQuantity?: number
reason?: string
remark?: string
}
export interface Reject {
rejectId: number
rejectCode: string
rejectDate: string
status: string
businessType: string
supplierId: number
supplierName: string
checkinId?: number
checkinCode?: string
totalQuantity?: number
outQuantity?: number
returnQuantity?: number
reason?: string
remark?: string
operatorName?: string
approverName?: string
approveDate?: string
lines: RejectLine[]
createTime?: string
}
export interface RejectQuery {
trackCode?: string
rejectCode?: string
itemCode?: string
itemName?: string
beginDate?: string
endDate?: string
status?: string
pageNum?: number
pageSize?: number
}
export interface RejectListResponse {
rows: Reject[]
total: number
}
// 获取采购退货单列表
export function getRejectList(params: RejectQuery): Promise<RejectListResponse> {
return request.get('/erp/po/reject/list', { params }).then((res: any) => {
return {
rows: res.rows || [],
total: res.total || 0
}
})
}
// 获取采购退货单详情
export function getRejectDetail(rejectId: number): Promise<Reject> {
return request.get(`/erp/po/reject/${rejectId}`).then((res: any) => {
return res.data
})
}
// 新增采购退货单
export function createReject(data: Partial<Reject>): Promise<void> {
return request.post('/erp/po/reject', data)
}
// 更新采购退货单
export function updateReject(data: Partial<Reject>): Promise<void> {
return request.put('/erp/po/reject', data)
}
// 删除采购退货单
export function deleteReject(rejectIds: string): Promise<void> {
return request.delete(`/erp/po/reject/${rejectIds}`)
}

View File

@@ -0,0 +1,105 @@
import axios from 'axios'
import { ElMessage, ElMessageBox } from 'element-plus'
import { getToken, removeToken } from '@/utils/auth'
import router from '@/router'
// 是否显示重新登录弹窗
let isReloginShowing = false
const request = axios.create({
baseURL: '',
timeout: 30000
})
// 请求拦截器
request.interceptors.request.use(
(config) => {
// 根据URL前缀动态设置baseURL
// 支持 /mes/*、/erp/* 和 /system/* 三种API地址
if (config.url) {
if (config.url.startsWith('/mes/')) {
// /mes/* 接口直接使用,不添加额外前缀
// 保持原样
} else if (config.url.startsWith('/erp/')) {
// /erp/* 接口直接使用,不添加额外前缀
// 保持原样
} else if (config.url.startsWith('/system/')) {
// /system/* 接口直接使用,不添加额外前缀(组织架构模块)
// 保持原样
} else {
// 其他接口默认添加 /erp 前缀
config.url = '/erp' + config.url
}
}
// 添加 Token 到请求头
const token = getToken()
if (token) {
config.headers = config.headers || {}
config.headers['Authorization'] = `Bearer ${token}`
}
return config
},
(error) => {
return Promise.reject(error)
}
)
// 响应拦截器
request.interceptors.response.use(
(response) => {
const res = response.data
const code = res.code || 200
// 处理 401 未授权
if (code === 401) {
if (!isReloginShowing) {
isReloginShowing = true
ElMessageBox.confirm(
'登录状态已过期,您可以继续留在该页面,或者重新登录',
'系统提示',
{
confirmButtonText: '重新登录',
cancelButtonText: '取消',
type: 'warning'
}
).then(() => {
isReloginShowing = false
removeToken()
router.push('/login')
}).catch(() => {
isReloginShowing = false
})
}
return Promise.reject(new Error('无效的会话,或者会话已过期,请重新登录。'))
}
// 处理其他错误码
if (code !== 200) {
const msg = res.msg || res.message || '请求失败'
ElMessage.error(msg)
return Promise.reject(new Error(msg))
}
return res
},
(error) => {
console.error('Request error:', error)
let message = error.message || '网络错误'
if (message === 'Network Error') {
message = '后端接口连接异常'
} else if (message.includes('timeout')) {
message = '系统接口请求超时'
} else if (message.includes('Request failed with status code')) {
const status = message.substring(message.length - 3)
message = `系统接口 ${status} 异常`
}
ElMessage.error(message)
return Promise.reject(error)
}
)
export default request

View File

@@ -0,0 +1,105 @@
import request from './request'
export interface SalebackLine {
lineId?: number
id?: number
salebackId?: number
salebackCode?: string
deliverLineId?: number
itemId?: number
itemCode?: string
materialCode?: string
itemName?: string
materialName?: string
specification?: string
spec?: string
unitOfMeasure?: string
unit?: string
returnQty: number
reason?: string
}
export interface Saleback {
salebackId?: number
id?: number
salebackCode?: string
code?: string
clientId?: number
customerId?: number
clientCode?: string
customerCode?: string
clientName?: string
customerName?: string
returnDate: string
status: string
totalQty?: number
reason?: string
remark?: string
lines?: SalebackLine[]
createTime?: string
}
export interface SalebackQuery {
code?: string
customerName?: string
status?: string
page?: number
pageSize?: number
}
export interface SalebackListResponse {
list: Saleback[]
total: number
}
// 获取退货单列表
export function getSalebackList(params: SalebackQuery): Promise<SalebackListResponse> {
return request.get('/erp/sl/saleback/list', { params }).then((res: any) => {
return {
list: res.rows || [],
total: res.total || 0
}
})
}
// 获取退货单详情
export function getSalebackDetail(id: number): Promise<Saleback> {
return request.get(`/erp/sl/saleback/${id}`).then((res: any) => {
return res.data
})
}
// 新增退货单
export function createSaleback(data: Partial<Saleback>): Promise<void> {
return request.post('/erp/sl/saleback', data)
}
// 更新退货单
export function updateSaleback(id: number, data: Partial<Saleback>): Promise<void> {
return request.put('/erp/sl/saleback', { ...data, salebackId: id })
}
// 删除退货单
export function deleteSaleback(id: number): Promise<void> {
return request.delete(`/erp/sl/saleback/${id}`)
}
// 审核退货单
export function auditSaleback(id: number): Promise<void> {
return request.post(`/erp/sl/saleback/audit/${id}`)
}
// 反审核退货单
export function unauditSaleback(id: number): Promise<void> {
return request.post(`/erp/sl/saleback/unaudit/${id}`)
}
// 引入发货单
export function getIntroduceDeliverList(params: any): Promise<SalebackListResponse> {
return request.get('/erp/sl/saleback/introduce', { params }).then((res: any) => {
return {
list: res.rows || [],
total: res.total || 0
}
})
}

View File

@@ -0,0 +1,268 @@
import request from './request'
// ============ 类型定义 ============
/** 订单明细行 */
export interface SalesOrderLine {
lineId?: number
orderId?: number
itemId?: number
itemCode?: string
itemName?: string
specification?: string
unitOfMeasure?: string
quantity?: number // 可选,新增时默认为空
unitPrice?: number
amount?: number
deliveredQty?: number
qualityReq?: string
remark?: string
delFlag?: string
}
/** 销售订单主表 */
export interface SalesOrder {
orderId?: number
orderCode?: string
orderName?: string
orderDate?: string
orderStatus?: string
// 客户信息
clientId?: number
clientCode?: string
clientName?: string
// 业务信息
contractNo?: string
bizType?: string
bizStatus?: string
salesType?: string
supplyMode?: string
deliveryStatus?: string
// 部门/人员
deptId?: number
deptName?: string
salesmanId?: number
salesmanName?: string
operatorId?: number
operatorName?: string
auditorId?: number
auditorName?: string
auditDate?: string
// 收货信息
receiver?: string
receiverPhone?: string
receiverAddress?: string
destCountry?: string
paymentTerms?: string
deliveryDate?: string
// 金额
totalAmount?: number
currency?: string
// 其他
remark?: string
delFlag?: string
createBy?: string
createTime?: string
updateBy?: string
updateTime?: string
// 明细行
lines?: SalesOrderLine[]
slaveList?: SalesOrderLine[]
}
/** 明细视图数据(展开物料维度) */
export interface SalesOrderDetailView {
orderId: number
orderCode: string
orderDate: string
orderStatus: string
contractNo?: string
clientId: number
clientName: string
salesmanName?: string
salesType?: string
// 物料信息
lineId: number
itemId: number
itemCode: string
itemName: string
specification?: string
quantity: number
unitPrice?: number
amount?: number
deliveredQty?: number
}
/** 查询参数 */
export interface SalesOrderQuery {
orderCode?: string
contractNo?: string
clientName?: string
salesmanName?: string
salesType?: string
itemName?: string
orderStatus?: string
beginOrderDate?: string
endOrderDate?: string
pageNum?: number
pageSize?: number
}
/** 分页响应 */
export interface SalesOrderListResponse {
list: SalesOrder[]
total: number
}
export interface SalesOrderDetailListResponse {
list: SalesOrderDetailView[]
total: number
}
// ============ 状态映射 ============
export const ORDER_STATUS_MAP: Record<string, { label: string; type: string }> = {
'DRAFT': { label: '草稿', type: 'info' },
'开立': { label: '开立', type: '' },
'审核': { label: '审核', type: 'success' },
'退回': { label: '退回', type: 'warning' },
'关闭': { label: '关闭', type: 'danger' }
}
export const SALES_TYPE_OPTIONS = [
{ value: 'factory', label: '工厂订单' },
{ value: 'stock', label: '库存供应' },
{ value: 'purchase', label: '买进卖出' }
]
export const SUPPLY_MODE_OPTIONS = [
{ value: 'plan', label: '计划生产' },
{ value: 'stock', label: '库存供应' }
]
export const DELIVERY_STATUS_OPTIONS = [
{ value: 'estimate', label: '预计' },
{ value: 'confirm', label: '确认' }
]
export const BIZ_TYPE_OPTIONS = [
{ value: 'sales_order', label: '销售订单' }
]
export const BIZ_STATUS_OPTIONS = [
{ value: 'normal', label: '正常' },
{ value: 'suspend', label: '挂起' }
]
// ============ API 接口 ============
const BASE = '/erp/sl/order'
/** 获取销售订单列表(单据视图) */
export function getSalesOrderList(params: SalesOrderQuery): Promise<SalesOrderListResponse> {
return request.get(`${BASE}/list`, { params }).then((res: any) => {
const rows = res.rows ?? res.data?.rows ?? []
const total = res.total ?? res.data?.total ?? 0
return { list: rows, total }
})
}
/** 获取销售订单明细列表(明细视图,展开物料维度) */
export function getSalesOrderDetailList(params: SalesOrderQuery): Promise<SalesOrderDetailListResponse> {
return request.get(`${BASE}/lineList`, { params }).then((res: any) => {
const rows = res.rows ?? res.data?.rows ?? []
const total = res.total ?? res.data?.total ?? 0
return { list: rows, total }
})
}
/** 获取销售订单详情(含明细行) */
export function getSalesOrderDetail(orderId: number): Promise<SalesOrder> {
return request.get(`${BASE}/${orderId}`).then((res: any) => {
const data = res.data ?? res
// 统一明细字段名
if (data.slaveList && !data.lines) {
data.lines = data.slaveList
}
// 后端返回 salesUserId/salesUserName前端表单使用 salesmanId/salesmanName便于下拉回显
if (data.salesUserId !== undefined) data.salesmanId = data.salesUserId
if (data.salesUserName !== undefined) data.salesmanName = data.salesUserName
return data
})
}
/** 构建保存用 payload明细转 slaveList销售人员字段对齐后端 salesUserId/salesUserName */
function buildOrderPayload(data: Partial<SalesOrder>): Record<string, unknown> {
const payload: Record<string, unknown> = { ...data }
if (payload.lines) {
payload.slaveList = payload.lines
delete payload.lines
}
// 后端实体为 salesUserId / salesUserName前端表单为 salesmanId / salesmanName此处统一发给后端
if (payload.salesmanId !== undefined) payload.salesUserId = payload.salesmanId
if (payload.salesmanName !== undefined) payload.salesUserName = payload.salesmanName
return payload
}
/** 新增销售订单 */
export function createSalesOrder(data: Partial<SalesOrder>): Promise<{ orderId: number }> {
return request.post(BASE, buildOrderPayload(data)).then((res: any) => res.data ?? res)
}
/** 更新销售订单 */
export function updateSalesOrder(data: Partial<SalesOrder>): Promise<void> {
return request.put(BASE, buildOrderPayload(data))
}
/** 删除销售订单(支持批量) */
export function deleteSalesOrder(orderIds: number | number[]): Promise<void> {
const ids = Array.isArray(orderIds) ? orderIds.join(',') : String(orderIds)
return request.delete(`${BASE}/${ids}`)
}
/** 审核销售订单(支持批量) */
export function auditSalesOrder(orderIds: number | number[]): Promise<void> {
if (orderIds == null || (Array.isArray(orderIds) && orderIds.length === 0)) {
return Promise.reject(new Error('订单ID不能为空'))
}
const ids = Array.isArray(orderIds) ? orderIds.join(',') : String(orderIds)
return request.post(`${BASE}/audit/${ids}`)
}
/** 反审核销售订单(支持批量) */
export function unauditSalesOrder(orderIds: number | number[]): Promise<void> {
if (orderIds == null || (Array.isArray(orderIds) && orderIds.length === 0)) {
return Promise.reject(new Error('订单ID不能为空'))
}
const ids = Array.isArray(orderIds) ? orderIds.join(',') : String(orderIds)
return request.post(`${BASE}/unaudit/${ids}`)
}
/** 导出销售订单 */
export function exportSalesOrder(params: SalesOrderQuery): Promise<Blob> {
return request.get(`${BASE}/export`, {
params,
responseType: 'blob'
})
}
// ============ 辅助接口 ============
/** 从销售合同引入订单明细 */
export function importFromContract(contractId: number): Promise<{ lines: SalesOrderLine[] }> {
return request.get(`/erp/sl/contract/${contractId}/lines`).then((res: any) => {
return { lines: res.data ?? res.rows ?? [] }
})
}
/** 获取可引入的合同列表 */
export function getAvailableContracts(clientId?: number): Promise<any[]> {
return request.get('/erp/sl/contract/available', { params: { clientId } }).then((res: any) => {
return res.rows ?? res.data ?? []
})
}
/** 生成订单编码(可选,后端自动生成时不需要) */
export function generateOrderCode(): Promise<string> {
return request.get(`${BASE}/generateCode`).then((res: any) => res.data ?? res)
}

View File

@@ -0,0 +1,155 @@
import request from './request'
// ============ 类型定义 ============
/** 供应商主数据 */
export interface Supplier {
vendorId?: number
vendorCode?: string
vendorName?: string
vendorNick?: string
vendorEn?: string
vendorDes?: string
vendorType?: string
vendorLevel?: string
vendorScore?: number
vendorLogo?: string
address?: string
province?: string
city?: string
zipCode?: string
website?: string
email?: string
tel?: string
fax?: string
contact1?: string
contact1Tel?: string
contact1Email?: string
contact2?: string
contact2Tel?: string
contact2Email?: string
creditCode?: string
bankName?: string
bankAccount?: string
bankAddress?: string
taxNo?: string
supplyItems?: string
remark?: string
enableFlag?: string
delFlag?: string
createBy?: string
createTime?: string
updateBy?: string
updateTime?: string
}
/** 查询参数 */
export interface SupplierQuery {
vendorCode?: string
vendorName?: string
vendorNick?: string
vendorEn?: string
vendorType?: string
vendorLevel?: string
enableFlag?: string
pageNum?: number
pageSize?: number
}
/** 分页响应 */
export interface SupplierListResponse {
rows: Supplier[]
total: number
}
// ============ 状态枚举 ============
/** 供应商等级选项 */
export const VENDOR_LEVEL_OPTIONS = [
{ value: 'A', label: 'A级' },
{ value: 'B', label: 'B级' },
{ value: 'C', label: 'C级' },
{ value: 'D', label: 'D级' }
]
/** 供应商类型选项 */
export const VENDOR_TYPE_OPTIONS = [
{ value: 'CORE', label: '核心供应商' },
{ value: 'NORMAL', label: '普通供应商' },
{ value: 'TEMP', label: '临时供应商' }
]
/** 是否启用选项 */
export const ENABLE_FLAG_OPTIONS = [
{ value: 'Y', label: '启用' },
{ value: 'N', label: '停用' }
]
// ============ API 接口 ============
const BASE = '/mes/md/vendor'
/** 获取供应商列表 */
export function getSupplierList(params: SupplierQuery): Promise<SupplierListResponse> {
return request.get(`${BASE}/list`, { params }).then((res: any) => {
const rows = res.rows ?? res.data?.rows ?? []
const total = res.total ?? res.data?.total ?? 0
return { rows, total }
})
}
/** 获取供应商详情 */
export function getSupplierDetail(vendorId: number): Promise<Supplier> {
return request.get(`${BASE}/${vendorId}`).then((res: any) => {
return res.data ?? res
})
}
/** 新增供应商 */
export function createSupplier(data: Partial<Supplier>): Promise<{ vendorId: number }> {
return request.post(BASE, data).then((res: any) => res.data ?? res)
}
/** 更新供应商 */
export function updateSupplier(data: Partial<Supplier>): Promise<void> {
return request.put(BASE, data)
}
/** 删除供应商(支持批量) */
export function deleteSupplier(vendorIds: number | number[] | string): Promise<void> {
const ids = Array.isArray(vendorIds) ? vendorIds.join(',') : String(vendorIds)
return request.delete(`${BASE}/${ids}`)
}
/** 导出供应商列表 */
export function exportSupplier(params: SupplierQuery): Promise<Blob> {
return request.get(`${BASE}/export`, {
params,
responseType: 'blob'
})
}
/** 下载导入模板 */
export function downloadImportTemplate(): Promise<Blob> {
return request.get(`${BASE}/importTemplate`, {
responseType: 'blob'
})
}
/** 导入供应商数据 */
export function importSupplier(file: File, updateSupport: boolean = false): Promise<any> {
const formData = new FormData()
formData.append('file', file)
return request.post(`${BASE}/importData?updateSupport=${updateSupport}`, formData, {
headers: { 'Content-Type': 'multipart/form-data' }
})
}
/** 获取供应商选项列表(用于下拉选择) */
export function getSupplierOptions(): Promise<Supplier[]> {
return request.get(`${BASE}/list`, {
params: { enableFlag: 'Y', pageNum: 1, pageSize: 1000 }
}).then((res: any) => {
return res.rows ?? res.data?.rows ?? []
})
}

View File

@@ -0,0 +1,91 @@
import request from '../request'
export interface Dept {
deptId?: number
parentId?: number
ancestors?: string
deptCode?: string
deptName?: string
orderNum?: number
leader?: string
phone?: string
email?: string
status?: string
delFlag?: string
createBy?: string
createTime?: string
updateBy?: string
updateTime?: string
children?: Dept[]
}
export interface DeptQuery {
deptName?: string
status?: string
}
const BASE = '/system/dept'
/** 查询部门列表 */
export function listDept(query?: DeptQuery): Promise<{ data: Dept[] }> {
return request.get(`${BASE}/list`, { params: query })
}
/** 查询部门列表(排除节点) */
export function listDeptExcludeChild(deptId: number): Promise<{ data: Dept[] }> {
return request.get(`${BASE}/list/exclude/${deptId}`)
}
/** 查询部门详细 */
export function getDept(deptId: number): Promise<{ data: Dept }> {
return request.get(`${BASE}/${deptId}`)
}
/** 查询部门下拉树结构 */
export function getDeptTreeselect(): Promise<{ data: any[] }> {
return request.get(`${BASE}/treeselect`)
}
/** 根据角色ID查询部门树结构 */
export function getRoleDeptTreeselect(roleId: number): Promise<{ data: any }> {
return request.get(`${BASE}/roleDeptTreeselect/${roleId}`)
}
/** 新增部门 */
export function addDept(data: Partial<Dept>): Promise<void> {
return request.post(BASE, data)
}
/** 修改部门 */
export function updateDept(data: Partial<Dept>): Promise<void> {
return request.put(BASE, data)
}
/** 删除部门 */
export function delDept(deptId: number): Promise<void> {
return request.delete(`${BASE}/${deptId}`)
}
/** 构建部门树 */
export function handleTree(data: Dept[], idField = 'deptId', parentField = 'parentId'): Dept[] {
const map = new Map<number, Dept>()
const result: Dept[] = []
data.forEach(item => {
map.set(item[idField as keyof Dept] as number, { ...item, children: [] })
})
data.forEach(item => {
const current = map.get(item[idField as keyof Dept] as number)!
const parentId = item[parentField as keyof Dept] as number
if (parentId && map.has(parentId)) {
const parent = map.get(parentId)!
parent.children = parent.children || []
parent.children.push(current)
} else {
result.push(current)
}
})
return result
}

View File

@@ -0,0 +1,58 @@
import request from '../request'
export interface Post {
postId?: number
postCode?: string
postName?: string
postSort?: number
status?: string
createBy?: string
createTime?: string
updateBy?: string
updateTime?: string
remark?: string
}
export interface PostQuery {
postCode?: string
postName?: string
status?: string
pageNum?: number
pageSize?: number
}
export interface PostListResponse {
rows: Post[]
total: number
}
const BASE = '/system/post'
/** 查询岗位列表 */
export function listPost(query?: PostQuery): Promise<PostListResponse> {
return request.get(`${BASE}/list`, { params: query }).then((res: any) => ({
rows: res.rows || [],
total: res.total || 0
}))
}
/** 查询岗位详细 */
export function getPost(postId: number): Promise<{ data: Post }> {
return request.get(`${BASE}/${postId}`)
}
/** 新增岗位 */
export function addPost(data: Partial<Post>): Promise<void> {
return request.post(BASE, data)
}
/** 修改岗位 */
export function updatePost(data: Partial<Post>): Promise<void> {
return request.put(BASE, data)
}
/** 删除岗位 */
export function delPost(postId: number | number[]): Promise<void> {
const ids = Array.isArray(postId) ? postId.join(',') : String(postId)
return request.delete(`${BASE}/${ids}`)
}

View File

@@ -0,0 +1,99 @@
import request from '../request'
export interface Role {
roleId?: number
roleName?: string
roleKey?: string
roleSort?: number
dataScope?: string
menuCheckStrictly?: boolean
deptCheckStrictly?: boolean
status?: string
delFlag?: string
createBy?: string
createTime?: string
updateBy?: string
updateTime?: string
remark?: string
menuIds?: number[]
deptIds?: number[]
}
export interface RoleQuery {
roleName?: string
roleKey?: string
status?: string
pageNum?: number
pageSize?: number
}
export interface RoleListResponse {
rows: Role[]
total: number
}
const BASE = '/system/role'
/** 查询角色列表 */
export function listRole(query?: RoleQuery): Promise<RoleListResponse> {
return request.get(`${BASE}/list`, { params: query }).then((res: any) => ({
rows: res.rows || [],
total: res.total || 0
}))
}
/** 查询角色详细 */
export function getRole(roleId: number): Promise<{ data: Role }> {
return request.get(`${BASE}/${roleId}`)
}
/** 新增角色 */
export function addRole(data: Partial<Role>): Promise<void> {
return request.post(BASE, data)
}
/** 修改角色 */
export function updateRole(data: Partial<Role>): Promise<void> {
return request.put(BASE, data)
}
/** 角色数据权限 */
export function dataScope(data: Partial<Role>): Promise<void> {
return request.put(`${BASE}/dataScope`, data)
}
/** 角色状态修改 */
export function changeRoleStatus(roleId: number, status: string): Promise<void> {
return request.put(`${BASE}/changeStatus`, { roleId, status })
}
/** 删除角色 */
export function delRole(roleId: number | number[]): Promise<void> {
const ids = Array.isArray(roleId) ? roleId.join(',') : String(roleId)
return request.delete(`${BASE}/${ids}`)
}
/** 查询角色已授权用户列表 */
export function allocatedUserList(query: any): Promise<any> {
return request.get(`${BASE}/authUser/allocatedList`, { params: query })
}
/** 查询角色未授权用户列表 */
export function unallocatedUserList(query: any): Promise<any> {
return request.get(`${BASE}/authUser/unallocatedList`, { params: query })
}
/** 取消用户授权角色 */
export function authUserCancel(data: any): Promise<void> {
return request.put(`${BASE}/authUser/cancel`, data)
}
/** 批量取消用户授权角色 */
export function authUserCancelAll(data: any): Promise<void> {
return request.put(`${BASE}/authUser/cancelAll`, data)
}
/** 授权用户选择 */
export function authUserSelectAll(data: any): Promise<void> {
return request.put(`${BASE}/authUser/selectAll`, data)
}

View File

@@ -0,0 +1,123 @@
import request from '../request'
export interface User {
userId?: number
deptId?: number
userName?: string
nickName?: string
userType?: string
email?: string
phonenumber?: string
sex?: string
avatar?: string
password?: string
status?: string
delFlag?: string
loginIp?: string
loginDate?: string
createBy?: string
createTime?: string
updateBy?: string
updateTime?: string
remark?: string
dept?: {
deptId?: number
deptName?: string
}
roles?: any[]
roleIds?: number[]
postIds?: number[]
}
export interface UserQuery {
userName?: string
phonenumber?: string
status?: string
deptId?: number
pageNum?: number
pageSize?: number
beginTime?: string
endTime?: string
}
export interface UserListResponse {
rows: User[]
total: number
}
const BASE = '/system/user'
/** 查询用户列表 */
export function listUser(query?: UserQuery): Promise<UserListResponse> {
return request.get(`${BASE}/list`, { params: query }).then((res: any) => ({
rows: res.rows || [],
total: res.total || 0
}))
}
/** 查询用户详细 */
export function getUser(userId?: number): Promise<{
data: User
roles: any[]
posts: any[]
postIds: number[]
roleIds: number[]
}> {
return request.get(userId ? `${BASE}/${userId}` : BASE)
}
/** 新增用户 */
export function addUser(data: Partial<User>): Promise<void> {
return request.post(BASE, data)
}
/** 修改用户 */
export function updateUser(data: Partial<User>): Promise<void> {
return request.put(BASE, data)
}
/** 删除用户 */
export function delUser(userId: number | number[]): Promise<void> {
const ids = Array.isArray(userId) ? userId.join(',') : String(userId)
return request.delete(`${BASE}/${ids}`)
}
/** 用户密码重置 */
export function resetUserPwd(userId: number, password: string): Promise<void> {
return request.put(BASE + '/resetPwd', { userId, password })
}
/** 用户状态修改 */
export function changeUserStatus(userId: number, status: string): Promise<void> {
return request.put(BASE + '/changeStatus', { userId, status })
}
/** 查询用户个人信息 */
export function getUserProfile(): Promise<{ data: User }> {
return request.get(`${BASE}/profile`)
}
/** 修改用户个人信息 */
export function updateUserProfile(data: Partial<User>): Promise<void> {
return request.put(`${BASE}/profile`, data)
}
/** 用户密码重置 */
export function updateUserPwd(oldPassword: string, newPassword: string): Promise<void> {
return request.put(`${BASE}/profile/updatePwd`, { oldPassword, newPassword })
}
/** 用户头像上传 */
export function uploadAvatar(data: FormData): Promise<{ imgUrl: string }> {
return request.post(`${BASE}/profile/avatar`, data)
}
/** 查询授权角色 */
export function getAuthRole(userId: number): Promise<{ user: User; roles: any[] }> {
return request.get(`${BASE}/authRole/${userId}`)
}
/** 保存授权角色 */
export function updateAuthRole(data: { userId: number; roleIds: string }): Promise<void> {
return request.put(`${BASE}/authRole`, data)
}

View File

@@ -0,0 +1,222 @@
import request from '../request'
// ============ 类型定义 ============
/** 生产领料单头 */
export interface IssueHeader {
issueId?: number
issueCode?: string
issueName?: string
workstationId?: number
workstationCode?: string
workstationName?: string
workorderId?: number
workorderCode?: string
taskId?: number
taskCode?: string
clientId?: number
clientCode?: string
clientName?: string
clientNick?: string
requiredTime?: string
issueDate?: string
status?: string
remark?: string
createBy?: string
createTime?: string
updateBy?: string
updateTime?: string
}
/** 查询参数 */
export interface IssueHeaderQuery {
issueCode?: string
issueName?: string
workorderCode?: string
workstationName?: string
status?: string
beginIssueDate?: string
endIssueDate?: string
pageNum?: number
pageSize?: number
}
/** 分页响应 */
export interface IssueHeaderListResponse {
rows: IssueHeader[]
total: number
}
// ============ 状态映射 ============
export const STATUS_MAP: Record<string, { label: string; type: string }> = {
'PREPARE': { label: '草稿', type: 'info' },
'CONFIRMED': { label: '已确认', type: '' },
'APPROVED': { label: '已审核', type: 'success' },
'FINISHED': { label: '已完成', type: 'success' }
}
// ============ API 接口 ============
const BASE = '/mes/wm/issueheader'
/** 查询领料单列表 */
export function getIssueHeaderList(params: IssueHeaderQuery): Promise<IssueHeaderListResponse> {
return request.get(`${BASE}/list`, { params }).then((res: any) => {
const rows = res.rows ?? res.data?.rows ?? []
const total = res.total ?? res.data?.total ?? 0
return { rows, total }
})
}
/** 获取领料单详情 */
export function getIssueHeaderDetail(issueId: number): Promise<IssueHeader> {
return request.get(`${BASE}/${issueId}`).then((res: any) => {
return res.data ?? res
})
}
/** 将日期字段规范为 yyyy-MM-dd HH:mm:ss后端 JsonFormat 要求) */
function normalizeDateFields(data: Partial<IssueHeader>): Partial<IssueHeader> {
const out = { ...data }
if (typeof out.issueDate === 'string' && out.issueDate.length === 10) {
out.issueDate = out.issueDate + ' 00:00:00'
}
if (typeof out.requiredTime === 'string' && out.requiredTime.length === 10) {
out.requiredTime = out.requiredTime + ' 00:00:00'
}
return out
}
/** 新增领料单,返回服务端生成的领料单对象(含 issueId、issueCode */
export function createIssueHeader(data: Partial<IssueHeader>): Promise<IssueHeader> {
return request.post(BASE, normalizeDateFields(data)).then((res: any) => res.data ?? res)
}
/** 修改领料单 */
export function updateIssueHeader(data: Partial<IssueHeader>): Promise<void> {
return request.put(BASE, normalizeDateFields(data))
}
/** 删除领料单(支持批量) */
export function deleteIssueHeader(ids: number | number[] | string): Promise<void> {
const idStr = Array.isArray(ids) ? ids.join(',') : String(ids)
return request.delete(`${BASE}/${idStr}`)
}
/** 执行出库 */
export function executeIssue(issueId: number): Promise<void> {
return request.put(`${BASE}/${issueId}`)
}
/** 校验领料数量与明细数量匹配 */
export function checkQuantity(issueId: number): Promise<boolean> {
return request.get(`${BASE}/checkQuantity/${issueId}`).then((res: any) => {
return res.data ?? res
})
}
/** 导出领料单 */
export function exportIssueHeader(params: IssueHeaderQuery): Promise<Blob> {
return request.post(`${BASE}/export`, params, { responseType: 'blob' })
}
// ============ 辅助选择 API ============
/** 工单列表(选择弹窗) */
export function getWorkorderSelectList(params?: {
workorderCode?: string
workorderName?: string
productName?: string
pageNum?: number
pageSize?: number
}): Promise<{ rows: any[]; total: number }> {
return request.get('/mes/pro/workorder/list', {
params: { pageNum: 1, pageSize: 100, ...params }
}).then((res: any) => ({
rows: res.rows ?? [],
total: res.total ?? 0
}))
}
/** 物料列表(选择弹窗) */
export function getItemSelectList(params?: {
itemCode?: string
itemName?: string
pageNum?: number
pageSize?: number
}): Promise<{ rows: any[]; total: number }> {
return request.get('/mes/md/mditem/list', {
params: { pageNum: 1, pageSize: 100, ...params }
}).then((res: any) => ({
rows: res.rows ?? [],
total: res.total ?? 0
}))
}
/** 客户列表(选择弹窗) */
export function getClientSelectList(params?: {
clientCode?: string
clientName?: string
pageNum?: number
pageSize?: number
}): Promise<{ rows: any[]; total: number }> {
return request.get('/mes/md/client/list', {
params: { pageNum: 1, pageSize: 100, ...params }
}).then((res: any) => ({
rows: res.rows ?? [],
total: res.total ?? 0
}))
}
/** 工作站列表(选择弹窗) */
export function getWorkstationSelectList(params?: {
workstationCode?: string
workstationName?: string
pageNum?: number
pageSize?: number
}): Promise<{ rows: any[]; total: number }> {
return request.get('/mes/md/workstation/list', {
params: { pageNum: 1, pageSize: 100, ...params }
}).then((res: any) => ({
rows: res.rows ?? [],
total: res.total ?? 0
}))
}
/** 仓库列表 */
export function getWarehouseList(params?: {
warehouseCode?: string
warehouseName?: string
}): Promise<{ rows: any[]; total: number }> {
return request.get('/mes/wm/warehouse/list', {
params: { pageNum: 1, pageSize: 200, ...params }
}).then((res: any) => ({
rows: res.rows ?? [],
total: res.total ?? 0
}))
}
/** 库区列表(按仓库筛选) */
export function getLocationList(params?: {
warehouseId?: number
}): Promise<{ rows: any[]; total: number }> {
return request.get('/mes/wm/location/list', {
params: { pageNum: 1, pageSize: 200, ...params }
}).then((res: any) => ({
rows: res.rows ?? [],
total: res.total ?? 0
}))
}
/** 库位列表(按库区筛选) */
export function getAreaList(params?: {
locationId?: number
}): Promise<{ rows: any[]; total: number }> {
return request.get('/mes/wm/area/list', {
params: { pageNum: 1, pageSize: 200, ...params }
}).then((res: any) => ({
rows: res.rows ?? [],
total: res.total ?? 0
}))
}

View File

@@ -0,0 +1,69 @@
import request from '../request'
// ============ 类型定义 ============
/** 出库明细 */
export interface IssueDetail {
detailId?: number
issueId?: number
lineId?: number
materialStockId?: string
itemId?: number
itemCode?: string
itemName?: string
specification?: string
unitOfMeasure?: string
unitName?: string
quantity?: number
batchId?: number
batchCode?: string
warehouseId?: number
warehouseCode?: string
warehouseName?: string
locationId?: number
locationCode?: string
locationName?: string
areaId?: number
areaCode?: string
areaName?: string
remark?: string
createBy?: string
createTime?: string
updateBy?: string
updateTime?: string
}
// ============ API 接口 ============
const BASE = '/mes/wm/issuedetail'
/** 查询出库明细列表 */
export function getIssueDetailList(params: {
issueId?: number
lineId?: number
pageNum?: number
pageSize?: number
}): Promise<{ rows: IssueDetail[]; total: number }> {
return request.get(`${BASE}/list`, {
params: { pageNum: 1, pageSize: 200, ...params }
}).then((res: any) => ({
rows: res.rows ?? res.data?.rows ?? [],
total: res.total ?? res.data?.total ?? 0
}))
}
/** 新增出库明细 */
export function createIssueDetail(data: Partial<IssueDetail>): Promise<number> {
return request.post(BASE, data).then((res: any) => res.data ?? res)
}
/** 修改出库明细 */
export function updateIssueDetail(data: Partial<IssueDetail>): Promise<void> {
return request.put(BASE, data)
}
/** 删除出库明细(支持批量) */
export function deleteIssueDetail(ids: number | number[] | string): Promise<void> {
const idStr = Array.isArray(ids) ? ids.join(',') : String(ids)
return request.delete(`${BASE}/${idStr}`)
}

View File

@@ -0,0 +1,59 @@
import request from '../request'
// ============ 类型定义 ============
/** 领料行 */
export interface IssueLine {
lineId?: number
issueId?: number
materialStockId?: number
itemId?: number
itemCode?: string
itemName?: string
specification?: string
unitOfMeasure?: string
unitName?: string
quantityIssued?: number
quantity?: number
batchId?: number
batchCode?: string
remark?: string
createBy?: string
createTime?: string
updateBy?: string
updateTime?: string
}
// ============ API 接口 ============
const BASE = '/mes/wm/issueline'
/** 查询领料行列表 */
export function getIssueLineList(params: {
issueId?: number
pageNum?: number
pageSize?: number
}): Promise<{ rows: IssueLine[]; total: number }> {
return request.get(`${BASE}/list`, {
params: { pageNum: 1, pageSize: 200, ...params }
}).then((res: any) => ({
rows: res.rows ?? res.data?.rows ?? [],
total: res.total ?? res.data?.total ?? 0
}))
}
/** 新增领料行 */
export function createIssueLine(data: Partial<IssueLine>): Promise<number> {
return request.post(BASE, data).then((res: any) => res.data ?? res)
}
/** 修改领料行 */
export function updateIssueLine(data: Partial<IssueLine>): Promise<void> {
return request.put(BASE, data)
}
/** 删除领料行(支持批量) */
export function deleteIssueLine(ids: number | number[] | string): Promise<void> {
const idStr = Array.isArray(ids) ? ids.join(',') : String(ids)
return request.delete(`${BASE}/${idStr}`)
}

View File

@@ -0,0 +1,305 @@
import request from './request'
// ============ 类型定义 ============
/** 生产工单 BOM 物料行 */
export interface WorkOrderBom {
lineId?: number
workorderId?: number
itemId?: number
itemCode?: string
itemName?: string
itemSpc?: string
unitOfMeasure?: string
unitName?: string
itemOrProduct?: string
quantity?: number
remark?: string
}
/** 生产工单主表 */
export interface WorkOrder {
workorderId?: number
workorderCode?: string
workorderName?: string
workorderType?: string
orderSource?: string
sourceCode?: string
productId?: number
productCode?: string
productName?: string
productSpc?: string
unitOfMeasure?: string
unitName?: string
routeId?: number
routeCode?: string
routeName?: string
batchCode?: string
quantity?: number
quantityProduced?: number
quantityChanged?: number
quantityScheduled?: number
clientId?: number
clientCode?: string
clientName?: string
vendorId?: number
vendorCode?: string
vendorName?: string
productionDate?: string // 前端字段名,映射到后端 requestDate
requestDate?: string // 后端实际字段名(数据库列 request_date
finishDate?: string
cancelDate?: string
parentId?: number
ancestors?: string
status?: string
remark?: string
createBy?: string
createTime?: string
updateBy?: string
updateTime?: string
// v3.1 新增字段
orderDate?: string // 单据日期
businessType?: string // 业务类型
businessStatus?: string // 业务状态
operatorName?: string // 操作员
approverName?: string // 审核员
approveDate?: string // 审核日期
salesOrderCode?: string // 跟单编号(销售订单号)
deliveryDate?: string // 订单交期
drawingNo?: string // 图纸号
productionLine?: string // 生产线
processTime?: number // 加工时长(分钟)
qualityReq?: string // 质量要求
}
/** 查询参数 */
export interface WorkOrderQuery {
workorderCode?: string
workorderName?: string
workorderType?: string
sourceCode?: string
productCode?: string
productName?: string
status?: string
beginProductionDate?: string // 前端用,映射到后端 beginRequestDate
endProductionDate?: string // 前端用,映射到后端 endRequestDate
pageNum?: number
pageSize?: number
}
/** 分页响应 */
export interface WorkOrderListResponse {
rows: WorkOrder[]
total: number
}
// ============ 状态映射 ============
export const STATUS_MAP: Record<string, { label: string; type: string }> = {
'PREPARE': { label: '草稿', type: 'info' },
'CONFIRMED': { label: '已确认', type: '' },
'APPROVED': { label: '已审核', type: 'success' },
'FINISHED': { label: '已完成', type: 'success' },
'CANCELED': { label: '已取消', type: 'danger' }
}
export const WORKORDER_TYPE_OPTIONS = [
{ value: 'SELF', label: '自产' },
{ value: 'OUTSOURCE', label: '委外' },
{ value: 'PROCESSING', label: '加工车间' }
]
export const BUSINESS_STATUS_OPTIONS = [
{ value: 'NORMAL', label: '正常' },
{ value: 'PAUSE', label: '暂停' },
{ value: 'CANCEL', label: '取消' }
]
// ============ API 接口 ============
const BASE = '/mes/pro/workorder'
/** 查询生产工单列表 */
export function getWorkOrderList(params: WorkOrderQuery): Promise<WorkOrderListResponse> {
// 将前端日期查询参数映射为后端字段名
const backendParams: Record<string, any> = { ...params }
if (backendParams.beginProductionDate) {
backendParams.beginRequestDate = backendParams.beginProductionDate
delete backendParams.beginProductionDate
}
if (backendParams.endProductionDate) {
backendParams.endRequestDate = backendParams.endProductionDate
delete backendParams.endProductionDate
}
return request.get(`${BASE}/list`, { params: backendParams }).then((res: any) => {
const rows = (res.rows ?? res.data?.rows ?? []).map((row: any) => {
// 后端返回 requestDate前端显示用 productionDate
if (row.requestDate && !row.productionDate) {
row.productionDate = row.requestDate
}
return row
})
const total = res.total ?? res.data?.total ?? 0
return { rows, total }
})
}
/** 获取生产工单详情 */
export function getWorkOrderDetail(workorderId: number): Promise<WorkOrder> {
return request.get(`${BASE}/${workorderId}`).then((res: any) => {
const data = res.data ?? res
// 后端返回 requestDate前端用 productionDate
if (data.requestDate && !data.productionDate) {
data.productionDate = data.requestDate
}
return data
})
}
/** 将前端字段名映射为后端字段名 */
function toBackendPayload(data: Partial<WorkOrder>): Record<string, any> {
const payload: Record<string, any> = { ...data }
// 前端用 productionDate后端用 requestDate
if (payload.productionDate !== undefined) {
payload.requestDate = payload.productionDate
delete payload.productionDate
}
return payload
}
/** 新增生产工单 */
export function createWorkOrder(data: Partial<WorkOrder>): Promise<number> {
return request.post(BASE, toBackendPayload(data)).then((res: any) => res.data ?? res)
}
/** 修改生产工单 */
export function updateWorkOrder(data: Partial<WorkOrder>): Promise<void> {
return request.put(BASE, toBackendPayload(data))
}
/** 删除生产工单(支持批量) */
export function deleteWorkOrder(workorderIds: number | number[] | string): Promise<void> {
const ids = Array.isArray(workorderIds) ? workorderIds.join(',') : String(workorderIds)
return request.delete(`${BASE}/${ids}`)
}
/** 完工工单 */
export function finishWorkOrder(workorderId: number): Promise<void> {
return request.put(`${BASE}/finish/${workorderId}`)
}
/** 取消工单 */
export function cancelWorkOrder(workorderId: number): Promise<void> {
return request.put(`${BASE}/cancel/${workorderId}`)
}
/** 获取工单 BOM 组成列表(直接查 pro_workorder_bom 表,字段名直接对应) */
export function getWorkOrderBomList(workorderId: number): Promise<WorkOrderBom[]> {
return request.get('/mes/pro/workorderbom/list', {
params: { workorderId, pageNum: 1, pageSize: 500 }
}).then((res: any) => {
return res.rows ?? res.data?.rows ?? []
})
}
/** 导出生产工单 */
export function exportWorkOrder(params: WorkOrderQuery): Promise<Blob> {
return request.post(`${BASE}/export`, params, { responseType: 'blob' })
}
/** 一键领料:根据工单 BOM 自动创建领料单,返回领料单 ID */
export function quickIssue(workorderId: number): Promise<number> {
return request.post(`${BASE}/quickIssue/${workorderId}`).then((res: any) => res.data ?? res)
}
/** 审核工单确认PREPARE → CONFIRMED */
export function confirmWorkOrder(workorderId: number): Promise<void> {
return request.put(`${BASE}/confirm/${workorderId}`)
}
/** 反审核工单CONFIRMED → PREPARE */
export function unconfirmWorkOrder(workorderId: number): Promise<void> {
return request.put(`${BASE}/unconfirm/${workorderId}`)
}
/** 查询工单关联的领料明细列表 */
export function getIssueListByWorkorder(workorderId: number): Promise<{ rows: any[]; total: number }> {
return request.get('/mes/wm/issueheader/list', {
params: { workorderId, pageNum: 1, pageSize: 100 }
}).then((res: any) => ({
rows: res.rows ?? [],
total: res.total ?? 0
}))
}
// ============ 工序任务ProTaskAPI ============
/** 工序任务 */
export interface ProTask {
taskId?: number
taskCode?: string
taskName?: string
workorderId?: number
workorderCode?: string
processId?: number
processCode?: string
processName?: string
quantity?: number
quantityProduced?: number
quantityQuanlified?: number
quantityUnquanlified?: number
startTime?: string
duration?: number
endTime?: string
colorCode?: string
status?: string
remark?: string
createBy?: string
createTime?: string
updateBy?: string
updateTime?: string
}
/** 根据工单 ID 获取工序任务列表 */
export function getTaskListByWorkorder(workorderId: number): Promise<ProTask[]> {
return request.get('/mes/pro/protask/list', {
params: { workorderId, pageNum: 1, pageSize: 500 }
}).then((res: any) => {
return res.rows ?? res.data?.rows ?? []
})
}
// ============ 工艺路线选择 API ============
/** 工艺路线列表(选择弹窗,不默认过滤 enableFlag 以避免列表为空) */
export function getRouteList(params?: {
routeCode?: string
routeName?: string
enableFlag?: string
pageNum?: number
pageSize?: number
}): Promise<{ rows: any[]; total: number }> {
return request.get('/mes/pro/proroute/list', {
params: { pageNum: 1, pageSize: 100, ...params }
}).then((res: any) => ({
rows: res.rows ?? [],
total: res.total ?? 0
}))
}
// ============ 客户选择 API备用 ============
/** 客户列表(选择弹窗) */
export function getClientList(params?: {
clientCode?: string
clientName?: string
pageNum?: number
pageSize?: number
}): Promise<{ rows: any[]; total: number }> {
return request.get('/mes/md/client/list', {
params: { pageNum: 1, pageSize: 100, ...params }
}).then((res: any) => ({
rows: res.rows ?? [],
total: res.total ?? 0
}))
}