Pārlūkot izejas kodu

迁移入股票后端api

yourname 7 mēneši atpakaļ
vecāks
revīzija
18dfa2d877
4 mainītis faili ar 150 papildinājumiem un 2 dzēšanām
  1. 1 1
      client/stock/stock_app.tsx
  2. 3 1
      server/router.ts
  3. 145 0
      server/routes_stock.ts
  4. 1 0
      版本迭代需求.md

+ 1 - 1
client/stock/stock_app.tsx

@@ -19,7 +19,7 @@ function StockApp() {
 //   const lastSentDateRef = useRef('');
   const [searchParams] = useSearchParams();
   const codeFromUrl = searchParams.get('code');
-  const [stockCode, setStockCode] = useState(codeFromUrl || undefined);// || '001339'
+  const [stockCode, setStockCode] = useState(codeFromUrl || '001339' || undefined);//
 //   const classroom = searchParams.get('classroom');
 //   const { connected } = useSocketRoom(classroom);
 //   const { sendNextQuestion } = useQuestionManagement(classroom);

+ 3 - 1
server/router.ts

@@ -18,6 +18,7 @@ import { createMigrationsRoutes } from "./routes_migrations.ts"
 import { createHomeRoutes } from "./routes_home.ts"
 
 import { createClassRoomRoutes } from "./routes_classroom.ts"
+import { createStockRoutes } from "./routes_stock.ts";
 
 export function createRouter(apiClient: APIClient, moduleDir: string) {
   const router = new Hono()
@@ -45,7 +46,8 @@ export function createRouter(apiClient: APIClient, moduleDir: string) {
   api.route('/migrations', createMigrationsRoutes(withAuth))
   api.route('/home', createHomeRoutes(withAuth))
 
-  api.route('/classroom', createClassRoomRoutes(withAuth)) // 添加课堂路由
+  api.route('/classroom', createClassRoomRoutes(withAuth))
+  api.route('/stock', createStockRoutes(withAuth));
   
 
   // 注册API路由到主路由器

+ 145 - 0
server/routes_stock.ts

@@ -0,0 +1,145 @@
+import { Hono } from 'hono'
+import type { Variables, WithAuth } from "./middlewares.ts";
+import debug from "debug";
+import dayjs from 'dayjs'
+
+interface ApiResponse<T = any> {
+  success: boolean;
+  code?: string;
+  message?: string;
+  data?: T;
+}
+
+interface DateNote {
+  date: string;
+  memo: string;
+  [key: string]: string;
+}
+
+const log = {
+  api: debug("api:stock"),
+};
+
+export function createStockRoutes(withAuth: WithAuth) {
+  const stockRoutes = new Hono<{ Variables: Variables }>()
+
+  stockRoutes.get('/history', async (c) => {
+    const apiClient = c.get('apiClient')
+    const url = new URL(c.req.url)
+    const code = url.searchParams.get("code") || '001339'
+    const dh = 'dn' // 固定值
+
+    if (!code || !dh) {
+      return c.text("Missing required parameters", 400)
+    }
+
+    try {
+      const license = Deno.env.get('STOCK_API_LICENSE')
+      if (!license) {
+        throw new Error('STOCK_API_LICENSE environment variable not set')
+      }
+
+      // 查询数据库中是否存在今天的数据
+      const today = dayjs().format('YYYY-MM-DD')
+      const existingData = await apiClient.database
+        .table("stock_data")
+        .select("*")
+        .where("code", code)
+        .where("updated_at", ">=", `${today} 00:00:00`)
+        .first()
+
+      if (existingData) {
+        return c.json(existingData.data)
+      }
+
+      // 如果没有今天的数据,调用外部API
+      const apiUrl = `http://api.mairui.club/hszbl/fsjy/${code}/${dh}/${license}`
+      const response = await fetch(apiUrl, {
+        method: "GET",
+        headers: {
+          "Accept": "application/json"
+        }
+      })
+
+      if (!response.ok) {
+        throw new Error(`API request failed with status ${response.status}`)
+      }
+
+      const newData = await response.json()
+
+      // 更新或插入数据库
+      await apiClient.database
+        .table("stock_data")
+        .insert({
+          code,
+          data: JSON.stringify(newData),
+          created_at: dayjs().format('YYYY-MM-DD HH:mm:ss'),
+          updated_at: dayjs().format('YYYY-MM-DD HH:mm:ss')
+        })
+        .onConflict("code")
+        .merge({
+          data: JSON.stringify(newData),
+          updated_at: dayjs().format('YYYY-MM-DD HH:mm:ss')
+        })
+        .execute()
+
+      return c.json(newData)
+
+    } catch (error) {
+      log.api("Error getting stock history:", error)
+      return c.text("Internal Server Error", 500)
+    }
+  })
+
+  stockRoutes.get('/memos', async (c) => {
+    const apiClient = c.get('apiClient')
+    const url = new URL(c.req.url)
+    const code = url.searchParams.get("code")
+
+    if (!code) {
+      const response: ApiResponse<Array<DateNote>> = {
+        success: true,
+        data: []
+      }
+      return c.json(response)
+    }
+
+    try {
+      const notes = await apiClient.database
+        .table("date_notes")
+        .select(["note_date as date", "note as memo"])
+        .where("code", code)
+        .orderBy("note_date", "asc")
+        .execute() as DateNote[]
+
+      if (!notes || notes.length === 0) {
+        const response: ApiResponse<Array<DateNote>> = {
+          success: true,
+          data: []
+        }
+        return c.json(response)
+      }
+
+      notes.forEach((note) => {
+        note.日期 = dayjs(note.date).format("YYYY-MM-DD")
+        note.提示 = note.memo
+      })
+
+      const response: ApiResponse<Array<DateNote>> = {
+        success: true,
+        data: notes
+      }
+      return c.json(response)
+    } catch (error) {
+      log.api("Error fetching memo data:", error)
+      const response: ApiResponse = {
+        success: false,
+        code: "SYSTEM.ERROR",
+        message: error instanceof Error ? error.message : "获取备忘录数据失败"
+      }
+      return c.json(response, 500)
+    }
+  })
+
+  return stockRoutes
+}

+ 1 - 0
版本迭代需求.md

@@ -1,4 +1,5 @@
 2025.05.15 0.1.1
+迁移入股票后端api
 添加股票日期备注表迁移
 添加股票历史数据表迁移
 添加股票训练入口