f7ce6f1058
- 分组支持 icon 字段,可按名称自动匹配或手动选择 - 左侧导航与总览卡片显示彩色 SVG 图标 - 优化侧栏链接圆角与选中态样式 Co-authored-by: Cursor <cursoragent@cursor.com>
81 lines
2.9 KiB
Python
81 lines
2.9 KiB
Python
from flask_wtf import FlaskForm
|
||
from wtforms import IntegerField, PasswordField, SelectField, StringField, SubmitField
|
||
from wtforms.validators import DataRequired, NumberRange, Optional, ValidationError
|
||
|
||
|
||
class LoginForm(FlaskForm):
|
||
username = StringField("用户名", validators=[DataRequired(message="请输入用户名")])
|
||
password = PasswordField("密码", validators=[DataRequired(message="请输入密码")])
|
||
submit = SubmitField("登录")
|
||
|
||
|
||
class GroupForm(FlaskForm):
|
||
name = StringField("分组名称", validators=[DataRequired(message="请输入分组名称")])
|
||
icon = SelectField(
|
||
"图标",
|
||
choices=[
|
||
("", "自动(按分组名匹配)"),
|
||
("order", "下单 / 订单"),
|
||
("trade", "交易 / 行情"),
|
||
("review", "复盘 / 历史"),
|
||
("api", "API / 接口"),
|
||
("gate", "Gate / 扫单"),
|
||
("chart", "图表 / K线"),
|
||
("server", "服务器 / 面板"),
|
||
("folder", "文件夹(通用)"),
|
||
],
|
||
default="",
|
||
validators=[Optional()],
|
||
)
|
||
sort_order = IntegerField(
|
||
"排序(越小越靠前)",
|
||
validators=[Optional(), NumberRange(min=-10**6, max=10**6)],
|
||
default=0,
|
||
)
|
||
submit = SubmitField("保存")
|
||
|
||
|
||
class ServiceForm(FlaskForm):
|
||
name = StringField("服务名称", validators=[DataRequired(message="请输入服务名称")])
|
||
scheme = SelectField(
|
||
"协议",
|
||
choices=[("http", "HTTP"), ("https", "HTTPS")],
|
||
default="http",
|
||
validators=[DataRequired(message="请选择协议")],
|
||
)
|
||
host = StringField(
|
||
"主机或域名",
|
||
validators=[DataRequired(message="请输入主机或域名")],
|
||
)
|
||
port = IntegerField(
|
||
"端口",
|
||
validators=[
|
||
DataRequired(message="请输入端口"),
|
||
NumberRange(min=1, max=65535, message="端口范围 1–65535"),
|
||
],
|
||
)
|
||
path = StringField("路径(可选,默认 /)", validators=[Optional()])
|
||
group_id = SelectField("分组", coerce=int, validators=[DataRequired(message="请选择分组")])
|
||
sort_order = IntegerField(
|
||
"排序(越小越靠前)",
|
||
validators=[Optional(), NumberRange(min=-10**6, max=10**6)],
|
||
default=0,
|
||
)
|
||
embed_kind = SelectField(
|
||
"嵌入类型",
|
||
choices=[
|
||
("", "普通(直接打开路径)"),
|
||
("hub", "复盘中控(云端 hub,需 embed-auth 登录)"),
|
||
("gate_scout", "Gate 扫描端(iframe 代登录)"),
|
||
("gate_exec", "Gate 执行器(iframe 代登录)"),
|
||
],
|
||
default="",
|
||
validators=[Optional()],
|
||
)
|
||
submit = SubmitField("保存")
|
||
|
||
def validate_path(self, field):
|
||
v = (field.data or "").strip()
|
||
if v and not v.startswith("/"):
|
||
raise ValidationError("路径需以 / 开头,例如 /admin")
|