|
|
@@ -0,0 +1,314 @@
|
|
|
+import { Hono } from "hono";
|
|
|
+import debug from "debug";
|
|
|
+import type {
|
|
|
+ SubmissionRecord,
|
|
|
+} from "../client/share/types_stock.ts";
|
|
|
+import {
|
|
|
+ SubmissionRecordStatus,
|
|
|
+} from "../client/share/types_stock.ts";
|
|
|
+
|
|
|
+import {
|
|
|
+ DeleteStatus,
|
|
|
+ EnableStatus,
|
|
|
+} from "../client/share/types.ts";
|
|
|
+
|
|
|
+import type { Variables, WithAuth } from "./middlewares.ts";
|
|
|
+
|
|
|
+const log = {
|
|
|
+ api: debug("api:submission"),
|
|
|
+};
|
|
|
+
|
|
|
+// 创建提交记录路由
|
|
|
+export function createSubmissionRoutes(withAuth: WithAuth) {
|
|
|
+ const submissionRoutes = new Hono<{ Variables: Variables }>();
|
|
|
+
|
|
|
+ // 创建提交记录
|
|
|
+ submissionRoutes.post("/", withAuth, async (c) => {
|
|
|
+ try {
|
|
|
+ const recordData = (await c.req.json()) as Partial<SubmissionRecord>;
|
|
|
+ const user = c.get("user");
|
|
|
+
|
|
|
+ // 验证必填字段
|
|
|
+ if (!recordData.code || !recordData.training_date) {
|
|
|
+ return c.json({ error: "股票代码和训练日期不能为空" }, 400);
|
|
|
+ }
|
|
|
+
|
|
|
+ const apiClient = c.get('apiClient');
|
|
|
+
|
|
|
+ // 设置提交者信息
|
|
|
+ if (user) {
|
|
|
+ recordData.user_id = user.id;
|
|
|
+ recordData.nickname = user.nickname || user.username;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置默认状态
|
|
|
+ recordData.status = SubmissionRecordStatus.PENDING;
|
|
|
+
|
|
|
+ // 插入提交记录
|
|
|
+ const [id] = await apiClient.database.table("submission_records").insert({
|
|
|
+ ...recordData,
|
|
|
+ is_disabled: EnableStatus.ENABLED,
|
|
|
+ is_deleted: DeleteStatus.NOT_DELETED,
|
|
|
+ created_at: apiClient.database.fn.now(),
|
|
|
+ updated_at: apiClient.database.fn.now(),
|
|
|
+ });
|
|
|
+
|
|
|
+ // 获取插入的数据
|
|
|
+ const [insertedRecord] = await apiClient.database
|
|
|
+ .table("submission_records")
|
|
|
+ .where("id", id);
|
|
|
+
|
|
|
+ return c.json({
|
|
|
+ message: "提交记录创建成功",
|
|
|
+ data: insertedRecord,
|
|
|
+ });
|
|
|
+ } catch (error) {
|
|
|
+ log.api("创建提交记录失败:", error);
|
|
|
+ return c.json({ error: "创建提交记录失败" }, 500);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 获取提交记录列表
|
|
|
+ submissionRoutes.get("/list", withAuth, async (c) => {
|
|
|
+ try {
|
|
|
+ const page = Number(c.req.query("page")) || 1;
|
|
|
+ const pageSize = Number(c.req.query("pageSize")) || 10;
|
|
|
+ const status = c.req.query("status");
|
|
|
+ const keyword = c.req.query("keyword");
|
|
|
+
|
|
|
+ const apiClient = c.get('apiClient');
|
|
|
+ let query = apiClient.database
|
|
|
+ .table("submission_records")
|
|
|
+ .where("is_deleted", DeleteStatus.NOT_DELETED)
|
|
|
+ .orderBy("created_at", "desc");
|
|
|
+
|
|
|
+ // 应用过滤条件
|
|
|
+ if (status) {
|
|
|
+ query = query.where("status", status);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (keyword) {
|
|
|
+ query = query.where((builder) => {
|
|
|
+ builder
|
|
|
+ .where("code", "like", `%${keyword}%`)
|
|
|
+ .orWhere("training_date", "like", `%${keyword}%`);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取总数
|
|
|
+ const total = await query.clone().count();
|
|
|
+
|
|
|
+ // 分页查询
|
|
|
+ const records = await query.limit(pageSize).offset((page - 1) * pageSize);
|
|
|
+
|
|
|
+ return c.json({
|
|
|
+ message: "获取提交记录列表成功",
|
|
|
+ data: {
|
|
|
+ list: records,
|
|
|
+ pagination: {
|
|
|
+ current: page,
|
|
|
+ pageSize,
|
|
|
+ total: Number(total),
|
|
|
+ },
|
|
|
+ },
|
|
|
+ });
|
|
|
+ } catch (error) {
|
|
|
+ log.api("获取提交记录列表失败:", error);
|
|
|
+ return c.json({ error: "获取提交记录列表失败" }, 500);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 获取单个提交记录
|
|
|
+ submissionRoutes.get("/:id", withAuth, async (c) => {
|
|
|
+ try {
|
|
|
+ const id = Number(c.req.param("id"));
|
|
|
+
|
|
|
+ if (!id || isNaN(id)) {
|
|
|
+ return c.json({ error: "无效的提交记录ID" }, 400);
|
|
|
+ }
|
|
|
+
|
|
|
+ const apiClient = c.get('apiClient');
|
|
|
+ const record = await apiClient.database
|
|
|
+ .table("submission_records")
|
|
|
+ .where("id", id)
|
|
|
+ .where("is_deleted", DeleteStatus.NOT_DELETED)
|
|
|
+ .first();
|
|
|
+
|
|
|
+ if (!record) {
|
|
|
+ return c.json({ error: "提交记录不存在" }, 404);
|
|
|
+ }
|
|
|
+
|
|
|
+ return c.json({
|
|
|
+ message: "获取提交记录成功",
|
|
|
+ data: record,
|
|
|
+ });
|
|
|
+ } catch (error) {
|
|
|
+ log.api("获取提交记录失败:", error);
|
|
|
+ return c.json({ error: "获取提交记录失败" }, 500);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 更新提交记录
|
|
|
+ submissionRoutes.put("/:id", withAuth, async (c) => {
|
|
|
+ try {
|
|
|
+ const id = Number(c.req.param("id"));
|
|
|
+ const recordData = (await c.req.json()) as Partial<SubmissionRecord>;
|
|
|
+
|
|
|
+ if (!id || isNaN(id)) {
|
|
|
+ return c.json({ error: "无效的提交记录ID" }, 400);
|
|
|
+ }
|
|
|
+
|
|
|
+ const apiClient = c.get('apiClient');
|
|
|
+
|
|
|
+ // 查询记录是否存在
|
|
|
+ const record = await apiClient.database
|
|
|
+ .table("submission_records")
|
|
|
+ .where("id", id)
|
|
|
+ .where("is_deleted", DeleteStatus.NOT_DELETED)
|
|
|
+ .first();
|
|
|
+
|
|
|
+ if (!record) {
|
|
|
+ return c.json({ error: "提交记录不存在" }, 404);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新记录
|
|
|
+ await apiClient.database
|
|
|
+ .table("submission_records")
|
|
|
+ .where("id", id)
|
|
|
+ .update({
|
|
|
+ ...recordData,
|
|
|
+ updated_at: apiClient.database.fn.now(),
|
|
|
+ });
|
|
|
+
|
|
|
+ // 获取更新后的数据
|
|
|
+ const [updatedRecord] = await apiClient.database
|
|
|
+ .table("submission_records")
|
|
|
+ .where("id", id);
|
|
|
+
|
|
|
+ return c.json({
|
|
|
+ message: "更新提交记录成功",
|
|
|
+ data: updatedRecord,
|
|
|
+ });
|
|
|
+ } catch (error) {
|
|
|
+ log.api("更新提交记录失败:", error);
|
|
|
+ return c.json({ error: "更新提交记录失败" }, 500);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 删除提交记录
|
|
|
+ submissionRoutes.delete("/:id", withAuth, async (c) => {
|
|
|
+ try {
|
|
|
+ const id = Number(c.req.param("id"));
|
|
|
+
|
|
|
+ if (!id || isNaN(id)) {
|
|
|
+ return c.json({ error: "无效的提交记录ID" }, 400);
|
|
|
+ }
|
|
|
+
|
|
|
+ const apiClient = c.get('apiClient');
|
|
|
+
|
|
|
+ // 查询记录是否存在
|
|
|
+ const record = await apiClient.database
|
|
|
+ .table("submission_records")
|
|
|
+ .where("id", id)
|
|
|
+ .where("is_deleted", DeleteStatus.NOT_DELETED)
|
|
|
+ .first();
|
|
|
+
|
|
|
+ if (!record) {
|
|
|
+ return c.json({ error: "提交记录不存在" }, 404);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 软删除记录
|
|
|
+ await apiClient.database.table("submission_records").where("id", id).update({
|
|
|
+ is_deleted: DeleteStatus.DELETED,
|
|
|
+ updated_at: apiClient.database.fn.now(),
|
|
|
+ });
|
|
|
+
|
|
|
+ return c.json({
|
|
|
+ message: "提交记录删除成功",
|
|
|
+ });
|
|
|
+ } catch (error) {
|
|
|
+ log.api("删除提交记录失败:", error);
|
|
|
+ return c.json({ error: "删除提交记录失败" }, 500);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 获取提交状态
|
|
|
+ submissionRoutes.get("/:id/status", withAuth, async (c) => {
|
|
|
+ try {
|
|
|
+ const id = Number(c.req.param("id"));
|
|
|
+
|
|
|
+ if (!id || isNaN(id)) {
|
|
|
+ return c.json({ error: "无效的提交记录ID" }, 400);
|
|
|
+ }
|
|
|
+
|
|
|
+ const apiClient = c.get('apiClient');
|
|
|
+ const record = await apiClient.database
|
|
|
+ .table("submission_records")
|
|
|
+ .where("id", id)
|
|
|
+ .where("is_deleted", DeleteStatus.NOT_DELETED)
|
|
|
+ .select("status")
|
|
|
+ .first();
|
|
|
+
|
|
|
+ if (!record) {
|
|
|
+ return c.json({ error: "提交记录不存在" }, 404);
|
|
|
+ }
|
|
|
+
|
|
|
+ return c.json({
|
|
|
+ message: "获取提交状态成功",
|
|
|
+ data: {
|
|
|
+ status: record.status,
|
|
|
+ },
|
|
|
+ });
|
|
|
+ } catch (error) {
|
|
|
+ log.api("获取提交状态失败:", error);
|
|
|
+ return c.json({ error: "获取提交状态失败" }, 500);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 更新提交状态
|
|
|
+ submissionRoutes.put("/:id/status", withAuth, async (c) => {
|
|
|
+ try {
|
|
|
+ const id = Number(c.req.param("id"));
|
|
|
+ const { status } = (await c.req.json()) as { status: SubmissionRecordStatus };
|
|
|
+
|
|
|
+ if (!id || isNaN(id)) {
|
|
|
+ return c.json({ error: "无效的提交记录ID" }, 400);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!status) {
|
|
|
+ return c.json({ error: "状态不能为空" }, 400);
|
|
|
+ }
|
|
|
+
|
|
|
+ const apiClient = c.get('apiClient');
|
|
|
+
|
|
|
+ // 查询记录是否存在
|
|
|
+ const record = await apiClient.database
|
|
|
+ .table("submission_records")
|
|
|
+ .where("id", id)
|
|
|
+ .where("is_deleted", DeleteStatus.NOT_DELETED)
|
|
|
+ .first();
|
|
|
+
|
|
|
+ if (!record) {
|
|
|
+ return c.json({ error: "提交记录不存在" }, 404);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新状态
|
|
|
+ await apiClient.database
|
|
|
+ .table("submission_records")
|
|
|
+ .where("id", id)
|
|
|
+ .update({
|
|
|
+ status,
|
|
|
+ updated_at: apiClient.database.fn.now(),
|
|
|
+ });
|
|
|
+
|
|
|
+ return c.json({
|
|
|
+ message: "更新提交状态成功",
|
|
|
+ });
|
|
|
+ } catch (error) {
|
|
|
+ log.api("更新提交状态失败:", error);
|
|
|
+ return c.json({ error: "更新提交状态失败" }, 500);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ return submissionRoutes;
|
|
|
+}
|