1
This commit is contained in:
parent
02b4f79137
commit
d7f7ad305c
@ -1,5 +1,9 @@
|
|||||||
FROM python:3.13-slim
|
FROM python:3.13-slim
|
||||||
|
|
||||||
|
# 设置东八区时区
|
||||||
|
ENV TZ=Asia/Shanghai
|
||||||
|
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY requirements.txt .
|
COPY requirements.txt .
|
||||||
|
|||||||
Binary file not shown.
@ -6,8 +6,10 @@ services:
|
|||||||
- ./backend/.env
|
- ./backend/.env
|
||||||
environment:
|
environment:
|
||||||
- ASTOCK_DATABASE_URL=sqlite:///./data/astock.db
|
- ASTOCK_DATABASE_URL=sqlite:///./data/astock.db
|
||||||
|
- TZ=Asia/Shanghai
|
||||||
volumes:
|
volumes:
|
||||||
- db_data:/app/data
|
- db_data:/app/data
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
expose:
|
expose:
|
||||||
- "8000"
|
- "8000"
|
||||||
# 生产环境不需要映射端口,前端容器通过 Docker 网络内部访问
|
# 生产环境不需要映射端口,前端容器通过 Docker 网络内部访问
|
||||||
@ -24,6 +26,9 @@ services:
|
|||||||
- backend
|
- backend
|
||||||
environment:
|
environment:
|
||||||
- BACKEND_URL=http://backend:8000
|
- BACKEND_URL=http://backend:8000
|
||||||
|
- TZ=Asia/Shanghai
|
||||||
|
volumes:
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
db_data:
|
db_data:
|
||||||
@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"pages": {
|
"pages": {
|
||||||
"/recommendations/page": [
|
"/page": [
|
||||||
"static/chunks/webpack.js",
|
"static/chunks/webpack.js",
|
||||||
"static/chunks/main-app.js",
|
"static/chunks/main-app.js",
|
||||||
"static/chunks/app/recommendations/page.js"
|
"static/chunks/app/page.js"
|
||||||
],
|
],
|
||||||
"/layout": [
|
"/layout": [
|
||||||
"static/chunks/webpack.js",
|
"static/chunks/webpack.js",
|
||||||
@ -11,15 +11,15 @@
|
|||||||
"static/css/app/layout.css",
|
"static/css/app/layout.css",
|
||||||
"static/chunks/app/layout.js"
|
"static/chunks/app/layout.js"
|
||||||
],
|
],
|
||||||
"/page": [
|
"/recommendations/page": [
|
||||||
"static/chunks/webpack.js",
|
"static/chunks/webpack.js",
|
||||||
"static/chunks/main-app.js",
|
"static/chunks/main-app.js",
|
||||||
"static/chunks/app/page.js"
|
"static/chunks/app/recommendations/page.js"
|
||||||
],
|
],
|
||||||
"/users/page": [
|
"/sectors/page": [
|
||||||
"static/chunks/webpack.js",
|
"static/chunks/webpack.js",
|
||||||
"static/chunks/main-app.js",
|
"static/chunks/main-app.js",
|
||||||
"static/chunks/app/users/page.js"
|
"static/chunks/app/sectors/page.js"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
2
frontend/.next/cache/.tsbuildinfo
vendored
2
frontend/.next/cache/.tsbuildinfo
vendored
File diff suppressed because one or more lines are too long
@ -1 +1,8 @@
|
|||||||
{}
|
{
|
||||||
|
"app/sectors/page.tsx -> echarts": {
|
||||||
|
"id": "app/sectors/page.tsx -> echarts",
|
||||||
|
"files": [
|
||||||
|
"static/chunks/_app-pages-browser_node_modules_echarts_index_js.js"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"/users/page": "app/users/page.js",
|
"/page": "app/page.js",
|
||||||
"/recommendations/page": "app/recommendations/page.js",
|
"/recommendations/page": "app/recommendations/page.js",
|
||||||
"/page": "app/page.js"
|
"/sectors/page": "app/sectors/page.js"
|
||||||
}
|
}
|
||||||
@ -1 +1 @@
|
|||||||
self.__REACT_LOADABLE_MANIFEST="{}"
|
self.__REACT_LOADABLE_MANIFEST="{\"app/sectors/page.tsx -> echarts\":{\"id\":\"app/sectors/page.tsx -> echarts\",\"files\":[\"static/chunks/_app-pages-browser_node_modules_echarts_index_js.js\"]}}"
|
||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"node": {},
|
"node": {},
|
||||||
"edge": {},
|
"edge": {},
|
||||||
"encryptionKey": "vMdxWQqJbs8lx1fn0MelZryKaOD9juru8raACaKF7MY="
|
"encryptionKey": "ep/FQ9LpllRmRWJwm9g4skQlubaCcrDQ9a9sMtJTxBw="
|
||||||
}
|
}
|
||||||
@ -125,7 +125,7 @@
|
|||||||
/******/
|
/******/
|
||||||
/******/ /* webpack/runtime/getFullHash */
|
/******/ /* webpack/runtime/getFullHash */
|
||||||
/******/ (() => {
|
/******/ (() => {
|
||||||
/******/ __webpack_require__.h = () => ("51f130523eab8ec6")
|
/******/ __webpack_require__.h = () => ("08a4c58ab1067fd1")
|
||||||
/******/ })();
|
/******/ })();
|
||||||
/******/
|
/******/
|
||||||
/******/ /* webpack/runtime/hasOwnProperty shorthand */
|
/******/ /* webpack/runtime/hasOwnProperty shorthand */
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@ -60,10 +60,23 @@ export default function DashboardPage() {
|
|||||||
}, [loadData]);
|
}, [loadData]);
|
||||||
|
|
||||||
useWebSocket(
|
useWebSocket(
|
||||||
useCallback(() => {
|
useCallback((msg: { type: string; count?: number; scan_mode?: string; message?: string }) => {
|
||||||
loadData();
|
if (msg.type === "scan_update") {
|
||||||
|
const modeLabel = msg.scan_mode === "intraday" ? "盘中实时" : "盘后";
|
||||||
|
setRefreshResult(`${modeLabel}扫描完成,发现 ${msg.count ?? 0} 只股票`);
|
||||||
|
setRefreshing(false);
|
||||||
|
loadData();
|
||||||
|
setTimeout(() => setRefreshResult(null), 5000);
|
||||||
|
} else if (msg.type === "scan_error") {
|
||||||
|
setRefreshResult("扫描失败,请重试");
|
||||||
|
setRefreshing(false);
|
||||||
|
setTimeout(() => setRefreshResult(null), 5000);
|
||||||
|
} else {
|
||||||
|
// 其他消息类型(如 llm_analysis_ready),刷新数据
|
||||||
|
loadData();
|
||||||
|
}
|
||||||
}, [loadData]),
|
}, [loadData]),
|
||||||
["llm_analysis_ready", "sector_scan_ready", "scan_complete"]
|
["scan_update", "scan_error", "llm_analysis_ready", "sector_scan_ready", "scan_complete"]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleRefresh = async () => {
|
const handleRefresh = async () => {
|
||||||
@ -72,18 +85,20 @@ export default function DashboardPage() {
|
|||||||
try {
|
try {
|
||||||
const res = await postAPI<{
|
const res = await postAPI<{
|
||||||
status: string;
|
status: string;
|
||||||
count: number;
|
message?: string;
|
||||||
temperature: number;
|
|
||||||
scan_mode: string;
|
|
||||||
is_trading: boolean;
|
is_trading: boolean;
|
||||||
}>("/api/recommendations/refresh?scan_session=manual");
|
}>("/api/recommendations/refresh?scan_session=manual");
|
||||||
const modeLabel = res.scan_mode === "intraday" ? "盘中实时" : "盘后";
|
|
||||||
setRefreshResult(`${modeLabel}扫描完成,发现 ${res.count} 只股票`);
|
if (res.status === "already_running") {
|
||||||
await loadData();
|
setRefreshResult(res.message || "扫描正在执行中,请稍候");
|
||||||
|
// 保持 refreshing,等待 WS 推送完成
|
||||||
|
} else if (res.status === "scanning") {
|
||||||
|
setRefreshResult("扫描已启动,完成后自动刷新...");
|
||||||
|
// 保持 refreshing,等待 WS 推送
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("刷新失败:", e);
|
console.error("触发扫描失败:", e);
|
||||||
setRefreshResult("扫描失败,请重试");
|
setRefreshResult("触发扫描失败,请重试");
|
||||||
} finally {
|
|
||||||
setRefreshing(false);
|
setRefreshing(false);
|
||||||
setTimeout(() => setRefreshResult(null), 5000);
|
setTimeout(() => setRefreshResult(null), 5000);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user