# -*- coding: utf-8 -*- """数据库模型""" from extensions import db class Provider(db.Model): """厂商(一个厂商对应多个配置)""" __tablename__ = "providers" id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(64), nullable=False, unique=True, index=True) official_url = db.Column(db.String(512), nullable=True) # 厂商默认官网 plans = db.relationship("VPSPlan", backref="provider_rel", lazy="dynamic", foreign_keys="VPSPlan.provider_id") class VPSPlan(db.Model): """云服务器配置/方案(属于某厂商)""" __tablename__ = "vps_plans" id = db.Column(db.Integer, primary_key=True) provider_id = db.Column(db.Integer, db.ForeignKey("providers.id"), nullable=True, index=True) # 关联厂商 provider = db.Column(db.String(64), nullable=True, index=True) # 冗余显示名,与 provider_id 二选一兼容旧数据 region = db.Column(db.String(128), nullable=True, index=True) # 保留兼容,不再在表单中填写 name = db.Column(db.String(128), nullable=True) # 可选,不填则用配置项生成显示 vcpu = db.Column(db.Integer, nullable=True) memory_gb = db.Column(db.Integer, nullable=True) storage_gb = db.Column(db.Integer, nullable=True) bandwidth_mbps = db.Column(db.Integer, nullable=True) traffic = db.Column(db.String(64), nullable=True) price_cny = db.Column(db.Float, nullable=True) price_usd = db.Column(db.Float, nullable=True) currency = db.Column(db.String(8), default="CNY") official_url = db.Column(db.String(512), nullable=True) # 该配置详情页,可覆盖厂商默认 countries = db.Column(db.String(255), nullable=True, index=True) @property def provider_name(self): if self.provider_rel: return self.provider_rel.name return self.provider or "" @property def display_name(self): """无规格名称时用配置项生成,如 2核4G 80GB""" if self.name and self.name.strip(): return self.name.strip() parts = [] if self.vcpu is not None: parts.append("{}核".format(self.vcpu)) if self.memory_gb is not None: parts.append("{}G".format(self.memory_gb)) if self.storage_gb is not None: parts.append("{}GB".format(self.storage_gb)) if self.traffic and self.traffic.strip(): parts.append(self.traffic.strip()) return " ".join(parts) if parts else "—" def to_dict(self): return { "id": self.id, "provider": self.provider_name, "region": self.region or "", "name": self.display_name, "vcpu": self.vcpu, "memory_gb": self.memory_gb, "storage_gb": self.storage_gb, "bandwidth_mbps": self.bandwidth_mbps, "traffic": self.traffic or "", "price_cny": float(self.price_cny) if self.price_cny is not None else None, "price_usd": float(self.price_usd) if self.price_usd is not None else None, "currency": self.currency or "CNY", "official_url": self.official_url or (self.provider_rel.official_url if self.provider_rel else "") or "", "countries": self.countries or "", }