修正今日

This commit is contained in:
侯欢 2025-12-07 23:55:28 +08:00
parent 616fe10b02
commit 339f8211e4
5 changed files with 37 additions and 4 deletions

View File

@ -64,6 +64,17 @@ curl -X PUT http://localhost:5000/api/admin/turnover \
--data-binary @revenue.csv
```
## 本地运行(默认数据库路径)
- 默认数据库:`sqlite:///data/data.db`(项目根目录下的 `data/data.db`
- 启动:
```powershell
$env:PORT=57778; $env:ADMIN_TOKEN="<你的口令>"; python backend/app.py
```
- 自定义路径Windows 绝对路径示例):
```powershell
$env:DATABASE_URL="sqlite:////e:/2025Code/python/YixuanYingye/data/data.db"; python backend/app.py
```
## 环境优化(最优解)
- 基础镜像切换为 `python:3.11-alpine`,构建更快、体积更小
- 依赖安装走腾讯云 PyPI 镜像:`PIP_INDEX_URL=https://mirrors.cloud.tencent.com/pypi/simple`

1
app.log Normal file
View File

@ -0,0 +1 @@
准备发送消息: 【益选便利店】2025-12-07的营业额2408.7

View File

@ -18,13 +18,21 @@ import io
load_dotenv()
app = Flask(__name__, static_folder="../frontend", static_url_path="/static")
CORS(app)
app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv("DATABASE_URL", "sqlite:///data.db")
app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv("DATABASE_URL", "sqlite:///data/data.db")
def _ensure_sqlite_dir(url):
if not url.startswith('sqlite:'):
return
p = url
if p.startswith('sqlite:////'):
db_path = p.replace('sqlite:////', '/')
db_path = p.replace('sqlite:////', '')
if db_path[1:3] == ':/' or db_path[1:3] == ':\\':
# path like 'E:/...' with a leading slash
pass
elif db_path[0:2] == ':/':
# unlikely
db_path = db_path[1:]
# Normalize Windows backslashes
db_path = db_path.replace('/', os.sep)
elif p.startswith('sqlite:///'):
db_path = os.path.join(os.getcwd(), p.replace('sqlite:///', ''))
else:
@ -95,13 +103,24 @@ def daily_job():
existing.source = existing.source or 'generator'
db.session.commit()
return
amount = generate_mock_revenue()
amount = gen_amount_for_date(today, cfg)
rev = DailyRevenue(date=today, amount=amount, is_final=True, source='generator')
db.session.add(rev)
db.session.add(AuditLog(date=today, old_amount=None, new_amount=amount, reason='daily_generate', actor='system', type='generate'))
db.session.commit()
_append_log_line(today.isoformat(), amount, shop_name)
def settle_today_if_due():
cfg = load_config()
cutoff = cfg.get("cutoff_hour", 23)
try:
cutoff = int(cutoff)
except Exception:
cutoff = 23
if datetime.now().hour < cutoff:
return
daily_job()
# ---- 日志解析与聚合 ----
def load_config():
cfg_path = os.path.join(os.path.dirname(__file__), "..", "config.json")
@ -349,6 +368,7 @@ if __name__ == "__main__":
with app.app_context():
sync_log_to_db()
auto_import_csv_on_start()
settle_today_if_due()
app.run(host="0.0.0.0", port=int(os.getenv("PORT", "5000")))
@app.route('/api/events')
@ -358,7 +378,8 @@ def sse_events():
now = datetime.now()
payload = {"type": "tick", "server_now": now.isoformat(timespec='seconds')}
yield f"data: {json.dumps(payload)}\n\n"
if now.hour == 23 and now.minute == 1:
if now.minute in (0, 1):
settle_today_if_due()
yield "data: {\"type\": \"force_refresh\"}\n\n"
time.sleep(30)
return Response(stream_with_context(event_stream()), mimetype='text/event-stream')

0
data/data.db Normal file
View File

Binary file not shown.