Browse Source

同步、测量、蓝牙、设置4模块接口mock

master
zhangjiming 4 months ago
parent
commit
f9157a8193
  1. 39
      package-lock.json
  2. 2
      package.json
  3. 6
      public/main.js
  4. 53
      src/index.ts
  5. 68
      src/routes/ble.ts
  6. 33
      src/routes/record.ts
  7. 42
      src/routes/sync.ts
  8. 20
      src/routes/system.ts
  9. 15
      src/types/apiTypes.ts
  10. 259
      src/utils/constant.ts

39
package-lock.json

@ -15,6 +15,7 @@
"express": "^5.0.1",
"morgan": "^1.10.0",
"multer": "^1.4.5-lts.1",
"ramda": "^0.30.1",
"ws": "^8.18.1"
},
"devDependencies": {
@ -24,6 +25,7 @@
"@types/morgan": "^1.9.9",
"@types/multer": "^1.4.12",
"@types/node": "^22.13.4",
"@types/ramda": "^0.30.2",
"@types/ws": "^8.5.14",
"nodemon": "^3.1.9",
"prisma": "^6.5.0",
@ -716,6 +718,16 @@
"dev": true,
"license": "MIT"
},
"node_modules/@types/ramda": {
"version": "0.30.2",
"resolved": "https://registry.npmmirror.com/@types/ramda/-/ramda-0.30.2.tgz",
"integrity": "sha512-PyzHvjCalm2BRYjAU6nIB3TprYwMNOUY/7P/N8bSzp9W/yM2YrtGtAnnVtaCNSeOZ8DzKyFDvaqQs7LnWwwmBA==",
"dev": true,
"license": "MIT",
"dependencies": {
"types-ramda": "^0.30.1"
}
},
"node_modules/@types/range-parser": {
"version": "1.2.7",
"resolved": "https://registry.npmmirror.com/@types/range-parser/-/range-parser-1.2.7.tgz",
@ -2063,6 +2075,16 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/ramda": {
"version": "0.30.1",
"resolved": "https://registry.npmmirror.com/ramda/-/ramda-0.30.1.tgz",
"integrity": "sha512-tEF5I22zJnuclswcZMc8bDIrwRHRzf+NqVEmqg50ShAZMP7MWeR/RGDthfM/p+BlqvF2fXAzpn8i+SJcYD3alw==",
"license": "MIT",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/ramda"
}
},
"node_modules/range-parser": {
"version": "1.2.1",
"resolved": "https://registry.npmmirror.com/range-parser/-/range-parser-1.2.1.tgz",
@ -2472,6 +2494,13 @@
}
}
},
"node_modules/ts-toolbelt": {
"version": "9.6.0",
"resolved": "https://registry.npmmirror.com/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz",
"integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==",
"dev": true,
"license": "Apache-2.0"
},
"node_modules/type-is": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/type-is/-/type-is-2.0.0.tgz",
@ -2492,6 +2521,16 @@
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
"license": "MIT"
},
"node_modules/types-ramda": {
"version": "0.30.1",
"resolved": "https://registry.npmmirror.com/types-ramda/-/types-ramda-0.30.1.tgz",
"integrity": "sha512-1HTsf5/QVRmLzcGfldPFvkVsAdi1db1BBKzi7iW3KBUlOICg/nKnFS+jGqDJS3YD8VsWbAh7JiHeBvbsw8RPxA==",
"dev": true,
"license": "MIT",
"dependencies": {
"ts-toolbelt": "^9.6.0"
}
},
"node_modules/typescript": {
"version": "5.7.3",
"resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.7.3.tgz",

2
package.json

@ -23,6 +23,7 @@
"express": "^5.0.1",
"morgan": "^1.10.0",
"multer": "^1.4.5-lts.1",
"ramda": "^0.30.1",
"ws": "^8.18.1"
},
"devDependencies": {
@ -32,6 +33,7 @@
"@types/morgan": "^1.9.9",
"@types/multer": "^1.4.12",
"@types/node": "^22.13.4",
"@types/ramda": "^0.30.2",
"@types/ws": "^8.5.14",
"nodemon": "^3.1.9",
"prisma": "^6.5.0",

6
public/main.js

@ -44,7 +44,7 @@ $("#endRecord").on("click", () => {
$('#disconnect-ble').on("click", ()=> {
$.ajax({
type: "POST",
url: "/api/cmd/disconnect-ble",
url: "/api/ble/disconnect",
data: JSON.stringify({}),
contentType: "application/json",
success: res => {
@ -58,8 +58,8 @@ $('#disconnect-ble').on("click", ()=> {
$('#connect-ble').on("click", ()=> {
$.ajax({
type: "POST",
url: "/api/cmd/connect-ble",
data: JSON.stringify({}),
url: "/api/ble/connect",
data: JSON.stringify({id: "abc"}),
contentType: "application/json",
success: res => {
console.log("Success", res);

53
src/index.ts

@ -3,10 +3,9 @@ import http from "http";
import bodyParser from "body-parser";
import morgan from "morgan";
import multer from "multer";
import cors from 'cors';
import cors from "cors";
import path from "path";
import cmdRouter from "./routes/cmd";
import authRouter from "./routes/auth";
import measureTaskRouter from "./routes/measureTask";
@ -16,6 +15,10 @@ import railRouter from "./routes/rail";
import calibrationRouter from "./routes/calibration";
import mobileRouter from "./routes/mobile";
import measureRouter from "./routes/measure";
import bleRouter from "./routes/ble";
import systemRouter from "./routes/system";
import syncRouter from "./routes/sync";
import recordRouter from "./routes/record";
// import { defaultStatus, StatusDatagram } from "./types/wsTypes";
import { WsProxy } from "./utils/wss";
@ -30,16 +33,16 @@ app.use(cors());
const server = http.createServer(app);
WsProxy.addActionForClientConnect((ws) => {
// DeviceContext
ws.send(
JSON.stringify({
messageType: "DeviceContext",
data: app.locals["context"],
path: "/deviceContext",
})
);
})
WsProxy.addActionForClientConnect(ws => {
// DeviceContext
ws.send(
JSON.stringify({
messageType: "DeviceContext",
data: app.locals["context"],
path: "/deviceContext",
})
);
});
// 在HTTP服务器上初始化WebSocket服务器
WsProxy.init(server);
// const wss = new Server({ server });
@ -61,37 +64,41 @@ app.use("/api/measurement-data", measureDataRouter);
app.use("/api/standard-rail", railRouter);
app.use("/api/calibration", calibrationRouter);
app.use("/api/measure", measureRouter);
app.use("/api/ble", bleRouter);
app.use("/api/system", systemRouter);
app.use("/api/sync", syncRouter);
app.use("/api/record", recordRouter);
const storage = multer.diskStorage({
destination: function (req, file, cb) {
// 指定文件存储的目录
cb(null, 'uploads/');
cb(null, "uploads/");
},
filename: function (req, file, cb) {
// 指定文件保存的文件名
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
cb(null, file.fieldname + '-' + uniqueSuffix + path.extname(file.originalname));
}
const uniqueSuffix = Date.now() + "-" + Math.round(Math.random() * 1e9);
cb(null, file.fieldname + "-" + uniqueSuffix + path.extname(file.originalname));
},
});
const upload = multer({ storage: storage });
// 创建上传文件的路由
app.post('/upload', upload.single('file'), (req, res) => {
app.post("/upload", upload.single("file"), (req, res) => {
if (!req.file) {
res.status(400).json({msg:'未收到文件'});
res.status(400).json({ msg: "未收到文件" });
} else {
res.json({msg:'文件上传成功!文件路径:' + req.file.path});
}
res.json({ msg: "文件上传成功!文件路径:" + req.file.path });
}
});
//@ts-ignore
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send("Something broke!");
console.error(err.stack);
res.status(500).send("Something broke!");
});
// 监听端口
const PORT = process.env.PORT || 8080;
server.listen(PORT, () => {
console.log(`Server is listening on port ${PORT}`);
console.log(`Server is listening on port ${PORT}`);
});

68
src/routes/ble.ts

@ -0,0 +1,68 @@
import express from "express";
import { delay, prismaClient } from "../utils/helper";
const router = express.Router();
import { WsProxy } from "../utils/wss";
let intervalId1: ReturnType<typeof setInterval>;
let connectId = "";
router.post("/list/start", (req, res) => {
intervalId1 = setInterval(() => {
WsProxy.sendMobile({
type: "ble-list",
data: [
{
mac: "xyz", // 蓝牙设备的 MAC 地址(唯一标识)
name: "TEST-XYZ", // 蓝牙设备的可读名称(如型号/别名)
linked: connectId === "xyz", //该设备是否已链接
},
{
mac: "abc", // 蓝牙设备的 MAC 地址(唯一标识)
name: "TEST-ABC", // 蓝牙设备的可读名称(如型号/别名)
linked: connectId === "abc", //该设备是否已链接
},
],
});
}, 1000);
res.json({ success: true });
});
router.post("/list/stop", (req, res) => {
clearInterval(intervalId1);
res.json({ success: true });
});
router.post("/connect", (req, res) => {
const id = req.body.id;
connectId = id;
setTimeout(() => {
WsProxy.sendMobile({
type: "peripheral-status",
data: {
connected: true, //是否已连接蓝牙
power: 60, //电量
inclinatorX: 0.276, //x轴倾斜
inclinatorY: 3.019, //y轴倾斜
temperature: 32.026, //温度
},
});
});
res.json({ success: true });
});
router.post("/disconnect", (req, res) => {
connectId = "";
setTimeout(() => {
WsProxy.sendMobile({
type: "peripheral-status",
data: {
connected: false, //是否已连接蓝牙
power: 60, //电量
inclinatorX: 0.276, //x轴倾斜
inclinatorY: 3.019, //y轴倾斜
temperature: 32.026, //温度
},
});
});
res.json({ success: true });
});
export default router;

33
src/routes/record.ts

@ -0,0 +1,33 @@
import express from "express";
import * as R from "ramda";
import { delay, prismaClient } from "../utils/helper";
const router = express.Router();
import { WsProxy } from "../utils/wss";
import { dataList, dataListFlat, dataListFlatMore } from "../utils/constant";
const settingObj = {
server: "",
};
router.post("/list", (req, res) => {
if (req.body.pageNum === 1) {
res.json({ success: true, data: { list: dataList } });
}
});
router.post("/detail", (req, res) => {
const id = +req.body.id;
const item = R.flatten(dataList.map(item => item.records)).find(t => t.id === id);
res.json({
success: true,
data: item || {},
});
});
router.post("/delete", (req, res) => {
const ids = req.body.ids;
res.json({ success: true });
});
export default router;

42
src/routes/sync.ts

@ -0,0 +1,42 @@
import express from "express";
import { delay, prismaClient } from "../utils/helper";
const router = express.Router();
import { WsProxy } from "../utils/wss";
import { dataListFlat, dataListFlatMore } from "../utils/constant";
const settingObj = {
server: "",
};
router.post("/list", (req, res) => {
if (req.body.pageNum === 1) {
res.json({ success: true, data: { list: dataListFlat } });
} else {
res.json({ success: true, data: { list: dataListFlatMore } });
}
});
router.post("/add", (req, res) => {
const ids = req.body.ids;
res.json({ success: true });
});
router.post("/progress", (req, res) => {
res.json({
success: true,
data: {
remaining: 123, // 剩余未同步数量
fail: 1, // 同步失败数量
total: 123, // 总数量
finish: false, // 是否同步完成(true 表示全部完成)
},
});
});
router.post("/config/save", (req, res) => {
const server = req.body.server;
settingObj.server = server;
res.json({ success: true });
});
export default router;

20
src/routes/system.ts

@ -0,0 +1,20 @@
import express from "express";
import { delay, prismaClient } from "../utils/helper";
const router = express.Router();
import { WsProxy } from "../utils/wss";
const settingObj = {
server: "",
};
router.post("/config", (req, res) => {
res.json({ success: true, data: settingObj });
});
router.post("/config/save", (req, res) => {
const server = req.body.server;
settingObj.server = server;
res.json({ success: true });
});
export default router;

15
src/types/apiTypes.ts

@ -0,0 +1,15 @@
export type Measurement = {
id: number;
name: string;
railId: number;
bureau: string;
line: string;
section: string;
direction: string;
createAt: string; // Date;
leftPoints: string; // json: 坐标数组
rightPoints: string; // json: 坐标数组
upload: boolean;
syncStatus: 'wait' | 'finish' | 'fail';
};

259
src/utils/constant.ts

@ -0,0 +1,259 @@
import { Measurement } from "../types/apiTypes";
export const dataListFlat: Measurement[] = [
{
id: 1,
name: "测量名称1",
createAt: "2025-03-02 10:20",
line: "京沪线",
section: "A段",
direction: "上行",
railId: 2,
leftPoints: "[]",
rightPoints: "[]",
bureau: "北京铁路局",
upload: false,
syncStatus: 'finish'
},
{
id: 2,
name: "测量名称2",
createAt: "2025-03-02 12:22",
line: "京沪线",
section: "B段",
direction: "下行",
railId: 2,
leftPoints: "[]",
rightPoints: "[]",
bureau: "北京铁路局",
upload: false,
syncStatus: 'finish'
},
{
id: 3,
name: "测量名称3",
createAt: "2025-03-02 12:20",
line: "京沪线",
section: "C段",
direction: "上行",
railId: 2,
leftPoints: "[]",
rightPoints: "[]",
bureau: "北京铁路局",
upload: false,
syncStatus: 'finish'
},
{
id: 4,
name: "测量名称3",
createAt: "2025-03-02 12:20",
line: "京沪线",
section: "C段",
direction: "上行",
railId: 2,
leftPoints: "[]",
rightPoints: "[]",
bureau: "北京铁路局",
upload: false,
syncStatus: 'finish'
},
{
id: 5,
name: "测量名称3",
createAt: "2025-03-02 12:20",
line: "京沪线",
section: "C段",
direction: "上行",
railId: 2,
leftPoints: "[]",
rightPoints: "[]",
bureau: "北京铁路局",
upload: false,
syncStatus: 'finish'
},
{
id: 6,
name: "测量名称3",
createAt: "2025-03-02 12:20",
line: "京沪线",
section: "C段",
direction: "上行",
railId: 2,
leftPoints: "[]",
rightPoints: "[]",
bureau: "北京铁路局",
upload: false,
syncStatus: 'finish'
},
{
id: 7,
name: "测量名称3",
createAt: "2025-03-02 12:20",
line: "京沪线",
section: "C段",
direction: "上行",
railId: 2,
leftPoints: "[]",
rightPoints: "[]",
bureau: "北京铁路局",
upload: false,
syncStatus: 'finish'
},
{
id: 8,
name: "测量名称3",
createAt: "2025-03-02 12:20",
line: "京沪线",
section: "C段",
direction: "上行",
railId: 2,
leftPoints: "[]",
rightPoints: "[]",
bureau: "北京铁路局",
upload: false,
syncStatus: 'finish'
},
{
id: 9,
name: "测量名称3",
createAt: "2025-03-02 12:20",
line: "京沪线",
section: "C段",
direction: "上行",
railId: 2,
leftPoints: "[]",
rightPoints: "[]",
bureau: "北京铁路局",
upload: false,
syncStatus: 'finish'
},
{
id: 10,
name: "测量名称3",
createAt: "2025-03-02 12:20",
line: "京沪线",
section: "C段",
direction: "上行",
railId: 2,
leftPoints: "[]",
rightPoints: "[]",
bureau: "北京铁路局",
upload: false,
syncStatus: 'finish'
},
];
export const dataListFlatMore: Measurement[] = [
{
id: 11,
name: "测量名称3",
createAt: "2025-03-02 12:20",
line: "京沪线",
section: "C段",
direction: "上行",
railId: 2,
leftPoints: "[]",
rightPoints: "[]",
bureau: "北京铁路局",
upload: false,
syncStatus: 'finish'
},
{
id: 12,
name: "测量名称3",
createAt: "2025-03-02 12:20",
line: "京沪线",
section: "C段",
direction: "上行",
railId: 2,
leftPoints: "[]",
rightPoints: "[]",
bureau: "北京铁路局",
upload: false,
syncStatus: 'finish'
},
];
export const dataList: Array<{ date: string; records: Measurement[] }> = [
{
date: '2025-03-02',
records: [
{
id: 1,
name: '测量名称1',
createAt: '2025-03-02 10:20',
line: '京沪线',
section: 'A段',
direction: '上行',
railId: 2,
leftPoints: '[]',
rightPoints: '[]',
bureau: '北京铁路局',
upload: false,
syncStatus: 'finish'
},
{
id: 2,
name: '测量名称2',
createAt: '2025-03-02 12:22',
line: '京沪线',
section: 'B段',
direction: '下行',
railId: 2,
leftPoints: '[]',
rightPoints: '[]',
bureau: '北京铁路局',
upload: false,
syncStatus: 'finish'
},
{
id: 3,
name: '测量名称3',
createAt: '2025-03-02 12:20',
line: '京沪线',
section: 'C段',
direction: '上行',
railId: 2,
leftPoints: '[]',
rightPoints: '[]',
bureau: '北京铁路局',
upload: false,
syncStatus: 'finish'
},
],
},
{
date: '2025-02-01',
records: [
{
id: 4,
name: '测量名称2',
createAt: '2025-03-02 10:20',
line: '京沪线',
section: 'D段',
direction: '下行',
railId: 2,
leftPoints: '[]',
rightPoints: '[]',
bureau: '北京铁路局',
upload: false,
syncStatus: 'finish'
},
{
id: 5,
name: '测量名称2',
createAt: '2025-03-02 10:20',
line: '京沪线',
section: 'E段',
direction: '下行',
railId: 2,
leftPoints: '[]',
rightPoints: '[]',
bureau: '北京铁路局',
upload: false,
syncStatus: 'finish'
},
],
},
];
Loading…
Cancel
Save