feat: 前后端全量开发 v0.2

后端:
- 客户模块 CRUD+搜索 (api/services/repositories 分层)
- 合同模块: FG单号规则/意向单转正式单/订单创建自动快照客户信息
- 优化下料: FFD首递减装箱算法(利用率统计/余料/未排入清单)
前端 (Vue3+TS+Element Plus):
- 7页面: 登录/工作台/订单中心/合同/客户/样板库/优化下料
- 自研二维窗型画布渲染器: 解析drawing_data渲染玻璃区域/外框/
  扇开向标记/尺寸标注, 支持缩放平移复位
- 样板库与订单联动(用此样板下单自动带图纸)
- axios统一envelope拦截/登录守卫/付费墙提示
工程:
- SPA history 回退路由, 构建产物挂载后端
- 全接口回归 6/6 通过
This commit is contained in:
HHY
2026-09-20 08:46:04 -07:00
parent d3e6de585c
commit f7a555dd6c
35 changed files with 3702 additions and 10 deletions
+106
View File
@@ -0,0 +1,106 @@
/** drawing_data 数据模型类型(与采集的 shapeManager 序化格式同构) */
export interface Pt { x: number; y: number; name?: string }
export interface Vec { x: number; y: number; name?: string }
export interface Segment { ps: Pt; pe: Pt; name?: string }
/** 中梃分割线 */
export interface SplitLine {
line: { pt: Pt; norm: Vec; name?: string }
polyId?: { idx: number; pos: number }
alignType?: number
equalSplit?: number
kw?: boolean // 竖撑
ws?: boolean // 窗撑
reinforced?: boolean
db?: boolean // hidden/disabled
}
/** 尺寸标注 */
export interface Dim {
at: number; ds: boolean
ov?: Vec
eidx?: number // 绑定外框边
midx?: number // 绑定中梃
name?: string
type?: 'line' | 'mullion' | string
}
export interface FrameModel {
ew?: [number, number, number, number] // 四边料宽
vs?: Pt[]
db?: unknown[]
ejw?: number[]
pew?: unknown[]
ast?: unknown[]
}
export interface ColorMap {
g?: string // 玻璃填充
bn?: string // 边框
hd?: string // 高光
ben?: string
}
export interface SashShape {
type: 'Sash' | string
bd?: { from: Pt; to: Pt; hidden?: boolean } // 扇所在区域包围盒
od?: number // 开向角度
opened?: boolean
wtf?: boolean // 带转框
isDoor?: boolean
polyId?: { idx: number; pos: number }
enabled?: boolean
rid?: string
[k: string]: unknown
}
export interface FrameShape {
type: 'Frame' | string
polygon?: {
type?: string
polygon?: Segment[][] // 分割后的玻璃区域(每区域为闭合段列表)
spLine?: SplitLine
ep?: string[]
virtual?: boolean
}
fm?: FrameModel
mm?: { sp: SplitLine[]; dbs?: unknown[]; fls?: unknown[]; phs?: unknown[]; lpfs?: unknown[] }
dm?: { dims: Dim[] }
cm?: ColorMap
sm?: SashShape[] // 子形状(扇)
ps?: Record<string, number>
uid?: string
titl?: string
[k: string]: unknown
}
export interface DrawingData {
s?: { cs?: number; cjs?: number }
cp?: unknown[]
sm: FrameShape[]
epi?: unknown[]
sbf?: unknown[]
wlc?: string
wall?: unknown[]
scale?: number
note?: unknown[]
}
/** 解析 drawing_data(兼容对象或 JSON 字符串) */
export function parseDrawing(raw: string | object): DrawingData {
const dd = typeof raw === 'string' ? JSON.parse(raw) : raw
return dd as DrawingData
}
/** 区域多边形 → 点列(段首点顺序连接) */
export function regionPoints(region: Segment[]): Pt[] {
return region.map(seg => ({ x: seg.ps.x, y: seg.ps.y }))
}
/** 点列包围盒 */
export function bboxOf(points: Pt[]): { x0: number; y0: number; x1: number; y1: number } {
const xs = points.map(p => p.x)
const ys = points.map(p => p.y)
return { x0: Math.min(...xs), y0: Math.min(...ys), x1: Math.max(...xs), y1: Math.max(...ys) }
}