diff --git a/app/src/main/java/com/iflytop/profilometer/api/ble/BleRoutes.kt b/app/src/main/java/com/iflytop/profilometer/api/ble/BleRoutes.kt index 8900975..8d64331 100644 --- a/app/src/main/java/com/iflytop/profilometer/api/ble/BleRoutes.kt +++ b/app/src/main/java/com/iflytop/profilometer/api/ble/BleRoutes.kt @@ -1,9 +1,11 @@ package com.iflytop.profilometer.api.ble import android.content.Context +import cn.hutool.json.JSONUtil import io.ktor.http.ContentType import io.ktor.server.application.call import io.ktor.server.request.receive +import io.ktor.server.request.receiveText import io.ktor.server.response.respondText import io.ktor.server.routing.Routing import io.ktor.server.routing.post @@ -31,8 +33,10 @@ fun Routing.bleRoutes(context: Context) { * 链接蓝牙设备 */ post("/api/ble/connect") { - val params = call.receive>() - val jsonResponse = api.connect(params["mac"]) + val requestBody = call.receiveText() + val jsonObj = JSONUtil.parseObj(requestBody) + val mac = jsonObj.getStr("mac") + val jsonResponse = api.connect(mac) call.respondText(jsonResponse, ContentType.Application.Json) } diff --git a/app/src/main/java/com/iflytop/profilometer/api/ble/BleWebsocketManager.java b/app/src/main/java/com/iflytop/profilometer/api/ble/BleWebsocketManager.java index 9116581..7169617 100644 --- a/app/src/main/java/com/iflytop/profilometer/api/ble/BleWebsocketManager.java +++ b/app/src/main/java/com/iflytop/profilometer/api/ble/BleWebsocketManager.java @@ -4,7 +4,6 @@ import android.annotation.SuppressLint; import android.bluetooth.BluetoothDevice; import android.content.Context; -import com.iflytop.profilometer.common.utils.GsonUtil; import com.iflytop.profilometer.core.bluetooth.BleManager; import com.iflytop.profilometer.core.websocket.WebSocketManager; diff --git a/app/src/main/java/com/iflytop/profilometer/api/record/RecordApi.java b/app/src/main/java/com/iflytop/profilometer/api/record/RecordApi.java index d2ef2ef..aef4aa3 100644 --- a/app/src/main/java/com/iflytop/profilometer/api/record/RecordApi.java +++ b/app/src/main/java/com/iflytop/profilometer/api/record/RecordApi.java @@ -4,6 +4,8 @@ import android.content.Context; import com.iflytop.profilometer.common.result.Result; import com.iflytop.profilometer.dao.ProfileRecordDao; +import com.iflytop.profilometer.dao.ProfileRecordPointSetDao; +import com.iflytop.profilometer.model.entity.ProfileRecordPointSet; import java.util.HashMap; import java.util.List; @@ -29,4 +31,13 @@ public class RecordApi { dataMap.put("list", dataList); return Result.success(dataMap); } + + /** + * 测量记录详情 + */ + public String detail(Long id){ + ProfileRecordPointSetDao profileRecordPointSetDao = new ProfileRecordPointSetDao(context); + ProfileRecordPointSet pointSet = profileRecordPointSetDao.getProfileRecordPointSetById(id); + return Result.success(pointSet); + } } diff --git a/app/src/main/java/com/iflytop/profilometer/api/record/RecordRoutes.kt b/app/src/main/java/com/iflytop/profilometer/api/record/RecordRoutes.kt index dac6cbf..059bd2b 100644 --- a/app/src/main/java/com/iflytop/profilometer/api/record/RecordRoutes.kt +++ b/app/src/main/java/com/iflytop/profilometer/api/record/RecordRoutes.kt @@ -28,17 +28,15 @@ fun Routing.recordRoutes(context: Context) { call.respondText(jsonResponse, ContentType.Application.Json) } - - /** - * 根据筛选条件获取测量记录列表 - */ - post("/api/record/list/search") { - } - /** * 测量记录详情 */ post("/api/record/detail") { + val requestBody = call.receiveText() + val jsonObj = JSONUtil.parseObj(requestBody) + val id = jsonObj.getLong("id") + val jsonResponse = api.detail(id) + call.respondText(jsonResponse, ContentType.Application.Json) } /** diff --git a/app/src/main/java/com/iflytop/profilometer/api/sync/SyncApi.java b/app/src/main/java/com/iflytop/profilometer/api/sync/SyncApi.java index 55139a8..befda68 100644 --- a/app/src/main/java/com/iflytop/profilometer/api/sync/SyncApi.java +++ b/app/src/main/java/com/iflytop/profilometer/api/sync/SyncApi.java @@ -2,6 +2,18 @@ package com.iflytop.profilometer.api.sync; import android.content.Context; +import com.iflytop.profilometer.common.result.Result; +import com.iflytop.profilometer.dao.ProfileRecordDao; +import com.iflytop.profilometer.dao.SyncTaskDao; +import com.iflytop.profilometer.model.entity.ProfileRecordDescription; +import com.iflytop.profilometer.model.entity.SyncTask; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import cn.hutool.json.JSONArray; + /** * 数据上传 */ @@ -12,5 +24,59 @@ public class SyncApi { this.context = context.getApplicationContext(); } + /** + * 同步任务列表 + */ + public String list(int pageNum, int size) { + SyncTaskDao syncTaskDao = new SyncTaskDao(context); + int total = syncTaskDao.getSyncTaskCount(); + List syncTaskList = syncTaskDao.getSyncTasks(pageNum, size); + Map dataMap = new HashMap<>(); + dataMap.put("total", total); + dataMap.put("list", syncTaskList); + return Result.success(dataMap); + } + + /** + * 添加同步任务 + */ + public String add(JSONArray ids) { + SyncTaskDao syncTaskDao = new SyncTaskDao(context); + ProfileRecordDao profileRecordDao = new ProfileRecordDao(context); + for (int i = 0; i < ids.size(); i++) { + Long id = ids.getLong(i); + ProfileRecordDescription profileRecordDescription = profileRecordDao.getProfileRecordById(id); + syncTaskDao.insertSyncTask(profileRecordDescription); + } + return Result.success(); + } + + /** + * 清空同步任务列表 + */ + public String emptyAll() { + SyncTaskDao syncTaskDao = new SyncTaskDao(context); + syncTaskDao.clearSyncTasks(); + return Result.success(); + } + + /** + * 清空已完成的同步任务 + */ + public String emptyFinish() { + SyncTaskDao syncTaskDao = new SyncTaskDao(context); + syncTaskDao.deleteFinishedSyncTasks(); + return Result.success(); + } + + public String reFail() { + SyncTaskDao syncTaskDao = new SyncTaskDao(context); + List syncTaskList = syncTaskDao.getUnfinishedSyncTasks(); + for (SyncTask syncTask : syncTaskList) { + + } + return Result.success(); + } + } diff --git a/app/src/main/java/com/iflytop/profilometer/api/sync/SyncRoutes.kt b/app/src/main/java/com/iflytop/profilometer/api/sync/SyncRoutes.kt index bbe5937..0b42790 100644 --- a/app/src/main/java/com/iflytop/profilometer/api/sync/SyncRoutes.kt +++ b/app/src/main/java/com/iflytop/profilometer/api/sync/SyncRoutes.kt @@ -1,9 +1,17 @@ package com.iflytop.profilometer.api.sync import android.content.Context +import cn.hutool.json.JSONUtil +import io.ktor.http.ContentType +import io.ktor.server.application.call +import io.ktor.server.request.receiveText +import io.ktor.server.response.respondText import io.ktor.server.routing.Routing import io.ktor.server.routing.post +/** + * 同步任务接口 + */ fun Routing.syncRoutes(context: Context) { val api = SyncApi(context) @@ -11,12 +19,30 @@ fun Routing.syncRoutes(context: Context) { * 同步任务列表 */ post("/api/sync/list") { + val requestBody = call.receiveText() + val jsonObj = JSONUtil.parseObj(requestBody) + val pageNum = jsonObj.getInt("pageNum", 1) + val size = jsonObj.getInt("size", 10) + val jsonResponse = api.list(pageNum, size) + call.respondText(jsonResponse, ContentType.Application.Json) + } + /** + * 添加同步任务 + */ + post("/api/sync/add") { + val requestBody = call.receiveText() + val jsonObj = JSONUtil.parseObj(requestBody) + val ids = jsonObj.getJSONArray("ids") + val jsonResponse = api.add(ids) + call.respondText(jsonResponse, ContentType.Application.Json) } /** * 清空同步任务列表 */ post("/api/sync/empty-all") { + val jsonResponse = api.emptyAll() + call.respondText(jsonResponse, ContentType.Application.Json) } @@ -24,18 +50,23 @@ fun Routing.syncRoutes(context: Context) { * 清空已完成的同步任务 */ post("/api/sync/empty-finish") { + val jsonResponse = api.emptyFinish() + call.respondText(jsonResponse, ContentType.Application.Json) } /** * 重试失败任务 */ post("/api/sync/re-fail") { + val jsonResponse = api.reFail() + call.respondText(jsonResponse, ContentType.Application.Json) } /** * 上传测量记录到科天健 */ post("/api/sync/upload-ktj") { + } } diff --git a/app/src/main/java/com/iflytop/profilometer/common/result/Result.java b/app/src/main/java/com/iflytop/profilometer/common/result/Result.java index db47098..e9511ab 100644 --- a/app/src/main/java/com/iflytop/profilometer/common/result/Result.java +++ b/app/src/main/java/com/iflytop/profilometer/common/result/Result.java @@ -1,8 +1,6 @@ package com.iflytop.profilometer.common.result; -import com.iflytop.profilometer.common.utils.GsonUtil; - import java.util.HashMap; import java.util.Map; diff --git a/app/src/main/java/com/iflytop/profilometer/common/utils/GsonUtil.java b/app/src/main/java/com/iflytop/profilometer/common/utils/GsonUtil.java deleted file mode 100644 index 683e1be..0000000 --- a/app/src/main/java/com/iflytop/profilometer/common/utils/GsonUtil.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.iflytop.profilometer.common.utils; - -import com.google.gson.*; -import com.google.gson.reflect.TypeToken; - -import java.lang.reflect.Type; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.util.List; - -public class GsonUtil { - // 定义日期格式 - private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; - private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT); - - // 创建 LocalDateTime 的序列化器 - private static final JsonSerializer localDateTimeSerializer = new JsonSerializer() { - @Override - public JsonElement serialize(LocalDateTime src, Type typeOfSrc, JsonSerializationContext context) { - return new JsonPrimitive(src.format(formatter)); - } - }; - - // 创建 LocalDateTime 的反序列化器 - private static final JsonDeserializer localDateTimeDeserializer = new JsonDeserializer() { - @Override - public LocalDateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) - throws JsonParseException { - return LocalDateTime.parse(json.getAsString(), formatter); - } - }; - - // 使用 GsonBuilder 注册 LocalDateTime 的适配器,同时设置 java.util.Date 的格式 - private static final Gson gson = new GsonBuilder() - .registerTypeAdapter(LocalDateTime.class, localDateTimeSerializer) - .registerTypeAdapter(LocalDateTime.class, localDateTimeDeserializer) - .setDateFormat(DATE_FORMAT) - .create(); - - /** - * 对象转 JSON 字符串 - * - * @param object 要转换的对象 - * @return 对象对应的 JSON 字符串,若对象为 null 则返回空字符串 - */ - public static String toJson(Object object) { - if (object == null) { - return ""; - } - return gson.toJson(object); - } - - /** - * JSON 字符串转对象 - * - * @param json JSON 字符串 - * @param clazz 目标对象的 Class 类型 - * @param 目标对象的类型 - * @return 转换后的对象,转换失败时返回 null - */ - public static T fromJson(String json, Class clazz) { - if (json == null || json.isEmpty()) { - return null; - } - try { - return gson.fromJson(json, clazz); - } catch (JsonSyntaxException e) { - e.printStackTrace(); - return null; - } - } - - /** - * JSON 字符串转 List 对象 - * - * @param json JSON 字符串 - * @param clazz List 中元素的 Class 类型 - * @param List 中元素的类型 - * @return 转换后的 List 对象,转换失败时返回 null - */ - public static List fromJsonToList(String json, Class clazz) { - if (json == null || json.isEmpty()) { - return null; - } - try { - // 利用 TypeToken 获取泛型类型 - Type type = TypeToken.getParameterized(List.class, clazz).getType(); - return gson.fromJson(json, type); - } catch (JsonSyntaxException e) { - e.printStackTrace(); - return null; - } - } -} diff --git a/app/src/main/java/com/iflytop/profilometer/dao/SyncTaskDao.java b/app/src/main/java/com/iflytop/profilometer/dao/SyncTaskDao.java index 212706b..15ca659 100644 --- a/app/src/main/java/com/iflytop/profilometer/dao/SyncTaskDao.java +++ b/app/src/main/java/com/iflytop/profilometer/dao/SyncTaskDao.java @@ -112,6 +112,119 @@ public class SyncTaskDao { return list; } + @SuppressLint("Range") + public List getSyncTasks(int pageNum, int size) { + List list = new ArrayList<>(); + SQLiteDatabase db = dbHelper.getReadableDatabase(); + int offset = (pageNum - 1) * size; + // 使用 LIMIT 与 OFFSET 实现分页,排序采用 create_time 倒序排列 + String limitClause = offset + ", " + size; + Cursor cursor = db.query( + MyDatabaseHelper.TABLE_SYNC_TASK, // 表名 + null, // 查询所有列 + null, // selection + null, // selectionArgs + null, // groupBy + null, // having + "create_time DESC", // orderBy:按照 create_time 降序排列 + limitClause // 分页参数 + ); + if (cursor.moveToFirst()) { + do { + SyncTask task = new SyncTask(); + task.setId(cursor.getLong(cursor.getColumnIndex("id"))); + task.setUuid(cursor.getString(cursor.getColumnIndex("uuid"))); + task.setOperatorName(cursor.getString(cursor.getColumnIndex("operator_name"))); + task.setTrackShapeCode(cursor.getString(cursor.getColumnIndex("track_shape_code"))); + task.setVerificationMethodCode(cursor.getString(cursor.getColumnIndex("verification_method_code"))); + task.setName(cursor.getString(cursor.getColumnIndex("name"))); + task.setLineName(cursor.getString(cursor.getColumnIndex("line_name"))); + task.setLocation(cursor.getString(cursor.getColumnIndex("location"))); + task.setDirection(cursor.getString(cursor.getColumnIndex("direction"))); + String syncStatus = cursor.getString(cursor.getColumnIndex("sync_status")); + if (syncStatus != null) { + task.setSyncStatus(SyncStatus.valueOf(syncStatus)); + } + task.setCreateTime(LocalDateTime.parse(cursor.getString(cursor.getColumnIndex("create_time")), FORMATTER)); + task.setUpdateTime(LocalDateTime.parse(cursor.getString(cursor.getColumnIndex("update_time")), FORMATTER)); + list.add(task); + } while (cursor.moveToNext()); + } + cursor.close(); + db.close(); + return list; + } + + public int getSyncTaskCount() { + int count = 0; + SQLiteDatabase db = dbHelper.getReadableDatabase(); + Cursor cursor = db.rawQuery("SELECT COUNT(*) FROM " + MyDatabaseHelper.TABLE_SYNC_TASK, null); + if (cursor.moveToFirst()) { + count = cursor.getInt(0); + } + cursor.close(); + db.close(); + return count; + } + + /** + * 删除所有 sync_status 字段值为 "finish" 的同步任务记录 + * @return 被删除的记录数 + */ + public int deleteFinishedSyncTasks() { + SQLiteDatabase db = dbHelper.getWritableDatabase(); + // 注意:此处比较值为 "finish",若枚举常量为大写(如 FINISH),请相应修改 + int rows = db.delete(MyDatabaseHelper.TABLE_SYNC_TASK, "sync_status = ?", new String[]{"finish"}); + db.close(); + return rows; + } + + /** + * 获取所有 sync_status 字段值不等于 "finish" 的同步任务记录,按 create_time 倒序排列 + * @return 同步任务记录列表 + */ + @SuppressLint("Range") + public List getUnfinishedSyncTasks() { + List list = new ArrayList<>(); + SQLiteDatabase db = dbHelper.getReadableDatabase(); + // 按 create_time 倒序排列 + Cursor cursor = db.query( + MyDatabaseHelper.TABLE_SYNC_TASK, + null, + "sync_status <> ?", + new String[]{"finish"}, + null, + null, + "create_time DESC" + ); + if (cursor.moveToFirst()) { + do { + SyncTask task = new SyncTask(); + task.setId(cursor.getLong(cursor.getColumnIndex("id"))); + task.setUuid(cursor.getString(cursor.getColumnIndex("uuid"))); + task.setOperatorName(cursor.getString(cursor.getColumnIndex("operator_name"))); + task.setTrackShapeCode(cursor.getString(cursor.getColumnIndex("track_shape_code"))); + task.setVerificationMethodCode(cursor.getString(cursor.getColumnIndex("verification_method_code"))); + task.setName(cursor.getString(cursor.getColumnIndex("name"))); + task.setLineName(cursor.getString(cursor.getColumnIndex("line_name"))); + task.setLocation(cursor.getString(cursor.getColumnIndex("location"))); + task.setDirection(cursor.getString(cursor.getColumnIndex("direction"))); + String syncStatus = cursor.getString(cursor.getColumnIndex("sync_status")); + if (syncStatus != null) { + task.setSyncStatus(SyncStatus.valueOf(syncStatus)); + } + task.setCreateTime(LocalDateTime.parse(cursor.getString(cursor.getColumnIndex("create_time")), FORMATTER)); + task.setUpdateTime(LocalDateTime.parse(cursor.getString(cursor.getColumnIndex("update_time")), FORMATTER)); + list.add(task); + } while (cursor.moveToNext()); + } + cursor.close(); + db.close(); + return list; + } + + + // 根据 id 查询同步任务记录 @SuppressLint("Range") public SyncTask getSyncTaskById(long id) {