You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

197 lines
6.1 KiB
TypeScript

import request from '@/config/axios'
export interface RecipeConfigVO {
id: number
recipeCode: string
recipeName?: string
name?: string
recipeType?: string | number
recipeTypeId?: string | number
productId?: number
productName?: string
machineName?: string
machineId?: number
deviceId?: number
deviceName?: string
recipeDesc?: string
remark?: string
isEnable?: string | number
dataUnit?: string
createTime?: string
}
export interface RecipePointDetailVO {
id: number
recipeId: string | number
attributeId?: number
pointName?: string
pointType?: string
dataType?: string
dataUnit?: string
attributeName?: string
attributeType?: string
}
export interface RecipePointCandidateVO {
id: number
pointName: string
pointType: string
dataType: string
dataUnit: string
}
type PageResult<T> = { list: T[]; total: number }
const STORAGE_KEYS = {
pointCandidates: 'mock:recipeConfig:pointCandidates',
recipePointRelation: 'mock:recipeConfig:recipePointRelation'
} as const
const safeParseJson = <T>(value: string | null): T | undefined => {
if (!value) return undefined
try {
return JSON.parse(value) as T
} catch {
return undefined
}
}
const loadFromStorage = <T>(key: string, fallback: T): T => {
const parsed = safeParseJson<T>(window.localStorage.getItem(key))
return parsed ?? fallback
}
const saveToStorage = (key: string, value: any) => {
window.localStorage.setItem(key, JSON.stringify(value))
}
const buildMockPointCandidates = (): RecipePointCandidateVO[] => {
const pointTypes = ['模拟量', '开关量', '计算量']
const dataTypes = ['int', 'float', 'string', 'bool']
const units = ['kg', 'm³', '℃', 'A', 'V', '']
return Array.from({ length: 60 }).map((_, idx) => {
const no = String(idx + 1).padStart(3, '0')
return {
id: idx + 1,
pointName: `点位-${no}`,
pointType: pointTypes[idx % pointTypes.length],
dataType: dataTypes[idx % dataTypes.length],
dataUnit: units[idx % units.length]
}
})
}
const ensureMockSeeded = () => {
const pointCandidates = loadFromStorage<RecipePointCandidateVO[]>(STORAGE_KEYS.pointCandidates, [])
if (!pointCandidates.length) saveToStorage(STORAGE_KEYS.pointCandidates, buildMockPointCandidates())
const relation = loadFromStorage<Record<string, number[]>>(STORAGE_KEYS.recipePointRelation, {})
if (!Object.keys(relation).length) saveToStorage(STORAGE_KEYS.recipePointRelation, {})
}
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))
const paginate = <T>(items: T[], pageNo: number, pageSize: number): PageResult<T> => {
const safePageNo = Math.max(1, Number(pageNo) || 1)
const safePageSize = Math.max(1, Number(pageSize) || 10)
const start = (safePageNo - 1) * safePageSize
return {
total: items.length,
list: items.slice(start, start + safePageSize)
}
}
const contains = (value: string | undefined, keyword: string | undefined) => {
const v = (value ?? '').toLowerCase()
const k = (keyword ?? '').trim().toLowerCase()
if (!k) return true
return v.includes(k)
}
export const RecipeConfigApi = {
getRecipeConfigPage: async (params: any) => {
const finalParams = {
...(params ?? {}),
name: params?.name ?? params?.recipeName
}
return await request.get({ url: `/iot/recipe/page`, params: finalParams })
},
createRecipeConfig: async (data: Partial<RecipeConfigVO>) => {
const finalData = {
id: data.id,
name: data.name ?? data.recipeName,
recipeCode: data.recipeCode,
recipeTypeId: (data as any).recipeTypeId ?? data.recipeType,
productId: data.productId,
machineId: (data as any).machineId ?? data.deviceId,
recipeDesc: data.recipeDesc ?? data.remark,
isEnable: data.isEnable,
dataUnit: data.dataUnit
}
return await request.post({ url: `/iot/recipe/create`, data: finalData })
},
updateRecipeConfig: async (data: Partial<RecipeConfigVO>) => {
const finalData = {
id: data.id,
name: data.name ?? data.recipeName,
recipeCode: data.recipeCode,
recipeTypeId: (data as any).recipeTypeId ?? data.recipeType,
productId: data.productId,
machineId: (data as any).machineId ?? data.deviceId,
recipeDesc: data.recipeDesc ?? data.remark,
isEnable: data.isEnable,
dataUnit: data.dataUnit
}
return await request.put({ url: `/iot/recipe/update`, data: finalData })
},
deleteRecipeConfig: async (id: number) => {
return await request.delete({ url: `/iot/recipe/delete?id=` + id })
},
exportRecipeConfig: async (params: any) => {
const finalParams = {
...(params ?? {}),
name: params?.name ?? params?.recipeName
}
return await request.download({ url: `/iot/recipe/export-excel`, params: finalParams })
},
getPointCandidatePage: async (params: any): Promise<PageResult<RecipePointCandidateVO>> => {
ensureMockSeeded()
await sleep(80)
const keyword = params?.keyword
const pageNo = params?.pageNo
const pageSize = params?.pageSize
const list = loadFromStorage<RecipePointCandidateVO[]>(
STORAGE_KEYS.pointCandidates,
buildMockPointCandidates()
)
const filtered = keyword
? list.filter((item) => contains(item.pointName, keyword))
: list
return paginate(filtered, pageNo, pageSize)
},
getRecipePointDetailPage: async (params: any) => {
return await request.get({ url: `/iot/recipe-device-attribute/page`, params })
},
updateRecipeDeviceAttribute: async (data: { recipeId: string | number; ids: number[] }) => {
return await request.put({ url: `/iot/recipe-device-attribute/update`, data })
},
saveRecipePointConfig: async (data: { recipeId: string | number; attributeIds: number[] }) => {
ensureMockSeeded()
await sleep(120)
const relation = loadFromStorage<Record<string, number[]>>(STORAGE_KEYS.recipePointRelation, {})
relation[String(data.recipeId)] = Array.from(new Set(data.attributeIds ?? [])).filter((v) => {
return typeof v === 'number' && !Number.isNaN(v)
})
saveToStorage(STORAGE_KEYS.recipePointRelation, relation)
return true
}
}