更新配置修改页面
This commit is contained in:
parent
ddcc65c9fd
commit
98d5b36996
1
.idea/table_game_project.iml
generated
1
.idea/table_game_project.iml
generated
@ -4,6 +4,7 @@
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="jdk" jdkName="table_game" jdkType="Python SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="bootstrap" level="application" />
|
||||
</component>
|
||||
<component name="PyNamespacePackagesService">
|
||||
<option name="namespacePackageFolders">
|
||||
|
||||
@ -2,7 +2,7 @@ screen -S backend
|
||||
|
||||
conda activate tabel_game_admin
|
||||
|
||||
uvicorn backend.app.main:app --reload --host 127.0.0.1
|
||||
uvicorn backend.app.main:app --reload --host 127.0.0.1 --reload-include backend/config.conf
|
||||
|
||||
|
||||
|
||||
|
||||
@ -21,6 +21,7 @@ from .routers import admin_message
|
||||
from .routers import user_messages
|
||||
from .routers import bell
|
||||
from .routers import admin_strategy
|
||||
from .routers import admin_congif
|
||||
|
||||
|
||||
|
||||
@ -64,6 +65,9 @@ app.include_router(admin_message.router, prefix="/admin", tags=["Admin-Message"]
|
||||
|
||||
app.include_router(admin_strategy.router, prefix="/admin", tags=["Admin-Strategy"])
|
||||
|
||||
app.include_router(admin_congif.router, prefix="/admin", tags=["Admin-Config"])
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
59
backend/app/routers/admin_congif.py
Normal file
59
backend/app/routers/admin_congif.py
Normal file
@ -0,0 +1,59 @@
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from pydantic import BaseModel
|
||||
from ..services.admin_config_service import (
|
||||
get_price_config,
|
||||
get_night_config,
|
||||
update_points_rate,
|
||||
update_get_points_rate,
|
||||
update_night_start,
|
||||
update_night_end,
|
||||
update_price_minutes
|
||||
)
|
||||
from ..services.admin_table_service import _verify_admin_permission
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
class UpdatePointsRateRequest(BaseModel):
|
||||
token: str
|
||||
points_rate: float
|
||||
|
||||
class UpdateNightTimeRequest(BaseModel):
|
||||
token: str
|
||||
time: str # 格式:"HH:MM:SS"
|
||||
|
||||
class UpdatePriceMinutesRequest(BaseModel):
|
||||
token: str
|
||||
price_minutes: int
|
||||
|
||||
@router.get("/config/price")
|
||||
def get_price_config_api():
|
||||
return get_price_config()
|
||||
|
||||
@router.get("/config/night")
|
||||
def get_night_config_api():
|
||||
return get_night_config()
|
||||
|
||||
@router.post("/config/points-rate")
|
||||
def update_points_rate_api(request: UpdatePointsRateRequest):
|
||||
_verify_admin_permission(request.token)
|
||||
return update_points_rate(request.points_rate)
|
||||
|
||||
@router.post("/config/get-points-rate")
|
||||
def update_get_points_rate_api(request: UpdatePointsRateRequest):
|
||||
_verify_admin_permission(request.token)
|
||||
return update_get_points_rate(request.points_rate)
|
||||
|
||||
@router.post("/config/night-start")
|
||||
def update_night_start_api(request: UpdateNightTimeRequest):
|
||||
_verify_admin_permission(request.token)
|
||||
return update_night_start(request.time)
|
||||
|
||||
@router.post("/config/night-end")
|
||||
def update_night_end_api(request: UpdateNightTimeRequest):
|
||||
_verify_admin_permission(request.token)
|
||||
return update_night_end(request.time)
|
||||
|
||||
@router.post("/config/price-minutes")
|
||||
def update_price_minutes_api(request: UpdatePriceMinutesRequest):
|
||||
_verify_admin_permission(request.token)
|
||||
return update_price_minutes(request.price_minutes)
|
||||
80
backend/app/services/admin_config_service.py
Normal file
80
backend/app/services/admin_config_service.py
Normal file
@ -0,0 +1,80 @@
|
||||
import configparser
|
||||
from pathlib import Path
|
||||
from fastapi import HTTPException
|
||||
|
||||
config_path = Path("backend/config.conf")
|
||||
|
||||
def _save_config(config):
|
||||
try:
|
||||
with open(config_path, 'w') as configfile:
|
||||
config.write(configfile)
|
||||
except Exception as e:
|
||||
raise HTTPException(500, f"配置保存失败: {str(e)}")
|
||||
|
||||
def get_price_config():
|
||||
config = configparser.ConfigParser()
|
||||
config.read(config_path)
|
||||
return {
|
||||
"points_rate": float(config.get("price", "points_rate")),
|
||||
"get_points_rate": float(config.get("price", "get_points_rate"))
|
||||
}
|
||||
|
||||
def get_night_config():
|
||||
config = configparser.ConfigParser()
|
||||
config.read(config_path)
|
||||
return {
|
||||
"start_time": config.get("stay_up_late", "start_time"),
|
||||
"end_time": config.get("stay_up_late", "end_time"),
|
||||
"price_minutes": int(config.get("stay_up_late", "price_minutes"))
|
||||
}
|
||||
|
||||
def update_points_rate(new_rate: float):
|
||||
config = configparser.ConfigParser()
|
||||
config.read(config_path)
|
||||
config.set("price", "points_rate", str(new_rate))
|
||||
_save_config(config)
|
||||
return {"message": "积分抵扣率更新成功"}
|
||||
|
||||
def update_get_points_rate(new_rate: float):
|
||||
config = configparser.ConfigParser()
|
||||
config.read(config_path)
|
||||
config.set("price", "get_points_rate", str(new_rate))
|
||||
_save_config(config)
|
||||
return {"message": "积分获取率更新成功"}
|
||||
|
||||
def update_night_start(new_time: str):
|
||||
# 添加时间格式验证
|
||||
try:
|
||||
from datetime import datetime
|
||||
datetime.strptime(new_time, "%H:%M:%S")
|
||||
except ValueError:
|
||||
raise HTTPException(400, "时间格式应为 HH:MM:SS")
|
||||
|
||||
config = configparser.ConfigParser()
|
||||
config.read(config_path)
|
||||
config.set("stay_up_late", "start_time", new_time)
|
||||
_save_config(config)
|
||||
return {"message": "晚场开始时间更新成功"}
|
||||
|
||||
def update_night_end(new_time: str):
|
||||
# 同样添加时间验证
|
||||
try:
|
||||
from datetime import datetime
|
||||
datetime.strptime(new_time, "%H:%M:%S")
|
||||
except ValueError:
|
||||
raise HTTPException(400, "时间格式应为 HH:MM:SS")
|
||||
config = configparser.ConfigParser()
|
||||
config.read(config_path)
|
||||
config.set("stay_up_late", "end_time", new_time)
|
||||
_save_config(config)
|
||||
return {"message": "晚场结束时间更新成功"}
|
||||
|
||||
def update_price_minutes(minutes: int):
|
||||
if minutes <= 0:
|
||||
raise HTTPException(400, "分钟数必须大于0")
|
||||
|
||||
config = configparser.ConfigParser()
|
||||
config.read(config_path)
|
||||
config.set("stay_up_late", "price_minutes", str(minutes))
|
||||
_save_config(config)
|
||||
return {"message": "计费分钟间隔更新成功"}
|
||||
@ -20,6 +20,7 @@ def create_app():
|
||||
from frontend.routes.coupons import coupons_bp
|
||||
from frontend.routes.messages import messages_bp
|
||||
from frontend.routes.strategies import strategies_bp
|
||||
from frontend.routes.config import config_bp
|
||||
|
||||
app.config['DEBUG_TB_INTERCEPT_REDIRECTS'] = False
|
||||
toolbar = DebugToolbarExtension(app)
|
||||
@ -36,6 +37,7 @@ def create_app():
|
||||
app.register_blueprint(coupons_bp)
|
||||
app.register_blueprint(messages_bp)
|
||||
app.register_blueprint(strategies_bp)
|
||||
app.register_blueprint(config_bp)
|
||||
|
||||
# 添加自定义过滤器
|
||||
@app.template_filter('datetime')
|
||||
|
||||
58
frontend/routes/config.py
Normal file
58
frontend/routes/config.py
Normal file
@ -0,0 +1,58 @@
|
||||
from flask import Blueprint, render_template, session, redirect, url_for, flash, request
|
||||
import requests
|
||||
from frontend.config import Config
|
||||
|
||||
config_bp = Blueprint('config', __name__, url_prefix='/admin/config')
|
||||
|
||||
@config_bp.route('/manage', methods=['GET', 'POST'])
|
||||
def manage_config():
|
||||
if not session.get('token'):
|
||||
return redirect(url_for('auth.login'))
|
||||
|
||||
# 获取所有配置
|
||||
price_resp = requests.get(f"{Config.BASE_API_URL}/admin/config/price")
|
||||
night_resp = requests.get(f"{Config.BASE_API_URL}/admin/config/night")
|
||||
|
||||
config = {
|
||||
'price': price_resp.json() if price_resp.status_code == 200 else {},
|
||||
'night': night_resp.json() if night_resp.status_code == 200 else {}
|
||||
}
|
||||
print(config)
|
||||
|
||||
if request.method == 'POST':
|
||||
field = request.form.get('field')
|
||||
value = request.form.get('value')
|
||||
|
||||
# 定义所有配置项的API端点映射
|
||||
endpoints = {
|
||||
'points_rate': '/points-rate',
|
||||
'get_points_rate': '/get-points-rate',
|
||||
'start_time': '/night-start',
|
||||
'end_time': '/night-end',
|
||||
'price_minutes': '/price-minutes'
|
||||
}
|
||||
|
||||
# 构建请求参数
|
||||
json_data = {"token": session['token']}
|
||||
if field in ['points_rate', 'get_points_rate']:
|
||||
json_data[field] = float(value)
|
||||
elif field in ['start_time', 'end_time']:
|
||||
json_data['time' if field in ['start_time', 'end_time'] else field] = value
|
||||
else:
|
||||
json_data[field] = int(value)
|
||||
|
||||
resp = requests.post(
|
||||
f"{Config.BASE_API_URL}/admin/config{endpoints[field]}",
|
||||
json=json_data
|
||||
)
|
||||
|
||||
if resp.status_code == 200:
|
||||
flash("配置更新成功", "success")
|
||||
else:
|
||||
error_detail = resp.json().get('detail', '未知错误')
|
||||
flash(f"更新失败: {error_detail}", "danger")
|
||||
|
||||
return redirect(url_for('config.manage_config'))
|
||||
|
||||
return render_template('config/manage.html', config=config)
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
<meta charset="utf-8">
|
||||
<title>{% block title %}桌游厅点单系统管理后台{% endblock %}</title>
|
||||
<!-- Bootstrap CSS -->
|
||||
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
@ -78,6 +78,13 @@
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ url_for('strategies.list_strategies') }}">策略管理</a>
|
||||
</li>
|
||||
<!-- 修改导航项为单个入口 -->
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ url_for('config.manage_config') }}">
|
||||
<i class="fas fa-cog"></i> 系统配置
|
||||
</a>
|
||||
</li>
|
||||
|
||||
{% endif %}
|
||||
</ul>
|
||||
{% if session.token %}
|
||||
@ -109,7 +116,7 @@
|
||||
|
||||
<script>
|
||||
// 建立全局WebSocket连接
|
||||
const adminWS = new WebSocket(`ws://192.168.5.16:8000/bell/ws/admin`);
|
||||
const adminWS = new WebSocket(`ws://127.0.0.1:8000/bell/ws/admin`); // 修复WebSocket地址
|
||||
|
||||
// 处理接收到的消息
|
||||
adminWS.onmessage = function (event) {
|
||||
|
||||
88
frontend/templates/config/manage.html
Normal file
88
frontend/templates/config/manage.html
Normal file
@ -0,0 +1,88 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}系统配置管理{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container mt-4">
|
||||
<div class="row">
|
||||
<!-- 价格配置 -->
|
||||
<div class="col-md-6">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header bg-primary text-white">价格配置</div>
|
||||
<div class="card-body">
|
||||
<form method="post">
|
||||
<div class="form-group">
|
||||
<label>积分获取</label>
|
||||
<div class="form-text text-muted" style="font-size: 0.9em;">
|
||||
订单价格乘以该数后保留整数位为获取的积分值
|
||||
</div>
|
||||
<input type="number" step="0.01" name="value"
|
||||
value="{{ config.price.points_rate }}"
|
||||
class="form-control" required>
|
||||
<input type="hidden" name="field" value="points_rate">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary btn-block">更新</button>
|
||||
</form>
|
||||
|
||||
<hr>
|
||||
|
||||
<form method="post">
|
||||
<div class="form-group">
|
||||
<label>每个积分可以抵扣价格</label>
|
||||
<input type="number" step="0.01" name="value"
|
||||
value="{{ config.price.get_points_rate }}"
|
||||
class="form-control" required>
|
||||
<input type="hidden" name="field" value="get_points_rate">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary btn-block">更新</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 晚场配置 -->
|
||||
<div class="col-md-6">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header bg-info text-white">晚场配置</div>
|
||||
<div class="card-body">
|
||||
<form method="post">
|
||||
<div class="form-group">
|
||||
<label>开始时间</label>
|
||||
<input type="time" step="1" name="value"
|
||||
value="{{ config.night.start_time }}"
|
||||
class="form-control" required>
|
||||
<input type="hidden" name="field" value="start_time">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-info btn-block">更新</button>
|
||||
</form>
|
||||
|
||||
<hr>
|
||||
|
||||
<form method="post">
|
||||
<div class="form-group">
|
||||
<label>结束时间</label>
|
||||
<input type="time" step="1" name="value"
|
||||
value="{{ config.night.end_time }}"
|
||||
class="form-control" required>
|
||||
<input type="hidden" name="field" value="end_time">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-info btn-block">更新</button>
|
||||
</form>
|
||||
|
||||
<hr>
|
||||
|
||||
<form method="post">
|
||||
<div class="form-group">
|
||||
<label>每小时收取</label>
|
||||
<input type="number" name="value"
|
||||
value="{{ config.night.price_minutes }}"
|
||||
class="form-control" min="1" required>
|
||||
<input type="hidden" name="field" value="price_minutes">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-info btn-block">更新</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
Loading…
x
Reference in New Issue
Block a user