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
+43
View File
@@ -0,0 +1,43 @@
/** axios 实例:自动携带 token、统一处理 401/付费墙 */
import axios from 'axios'
import { ElMessage } from 'element-plus'
import router from '../router'
export const http = axios.create({ baseURL: '/', timeout: 30000 })
http.interceptors.request.use(cfg => {
const token = localStorage.getItem('hmc_token')
if (token) cfg.headers.Authorization = `Bearer ${token}`
return cfg
})
http.interceptors.response.use(
res => {
const d = res.data
if (d && typeof d === 'object' && 'code' in d) {
if (d.code === 1) return res
if (String(d.code) === '10086') {
ElMessage.warning(d.message ?? '该功能需要购买解锁')
return Promise.reject(new Error(d.message))
}
if (Number(d.code) === 401) {
localStorage.removeItem('hmc_token')
router.push('/login')
return Promise.reject(new Error(d.message))
}
ElMessage.error(d.message ?? '操作失败')
return Promise.reject(new Error(d.message))
}
return res
},
err => {
ElMessage.error(err.message ?? '网络错误')
return Promise.reject(err)
},
)
/** 提取 envelope 的 data */
export async function api<T = any>(method: string, url: string, body?: object): Promise<T> {
const res = await http.request({ method, url, data: body })
return res.data.data as T
}