流畅的光波显示:

项目地址:https://atomgit.com/feng8403000/fps60-renwuduizhan

一、武器系统概述

武器系统是游戏战斗机制的核心组成部分,负责定义武器的属性、攻击方式、伤害计算和视觉效果。本项目实现了一个灵活可扩展的武器系统,支持多种武器类型和攻击模式。

1.1 系统架构

┌─────────────────────────────────────────────────────────────┐
│                     武器系统架构                            │
├─────────────────────────────────────────────────────────────┤
│  ┌──────────────┐    ┌──────────────┐    ┌──────────────┐  │
│  │  武器数据层  │───▶│  武器逻辑层  │───▶│  武器视图层  │  │
│  │  (Weapon)   │    │ (WeaponLogic)│    │ (WeaponView) │  │
│  └──────────────┘    └──────────────┘    └──────────────┘  │
│         │                  │                  │             │
│         ▼                  ▼                  ▼             │
│  ┌──────────────────────────────────────────────────────┐   │
│  │                 战斗系统 (BattleSystem)               │   │
│  └──────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────┘

1.2 核心功能特性

功能模块 功能描述 技术实现
武器类型 支持多种武器类型(近战、远程、魔法) 枚举类型 + 工厂模式
属性系统 攻击力、攻击速度、射程、暴击率 数据对象封装
攻击模式 普通攻击、蓄力攻击、特殊技能 状态机管理
伤害计算 基础伤害、暴击伤害、元素伤害 公式计算 + 修饰器模式
视觉效果 攻击波、粒子特效、光效 组合动画 + 滤镜效果

二、武器数据模型

2.1 武器基础属性

// 武器类型枚举
enum WeaponType {
  MELEE = 'melee',      // 近战武器
  RANGED = 'ranged',    // 远程武器
  MAGIC = 'magic'       // 魔法武器
}

// 武器品质枚举
enum WeaponRarity {
  COMMON = 'common',        // 普通
  UNCOMMON = 'uncommon',    // 优秀
  RARE = 'rare',            // 稀有
  EPIC = 'epic',            // 史诗
  LEGENDARY = 'legendary'   // 传说
}

// 武器数据接口
interface WeaponData {
  id: string;                    // 武器ID
  name: string;                  // 武器名称
  type: WeaponType;              // 武器类型
  rarity: WeaponRarity;          // 品质
  attackPower: number;           // 攻击力
  attackSpeed: number;           // 攻击速度(攻击间隔ms)
  range: number;                 // 攻击射程(像素)
  criticalRate: number;          // 暴击率(0-1)
  criticalDamage: number;        // 暴击伤害倍率
  elementType?: ElementType;     // 元素类型
  elementPower?: number;         // 元素伤害
  description: string;           // 武器描述
}

// 元素类型
enum ElementType {
  FIRE = 'fire',
  ICE = 'ice',
  LIGHTNING = 'lightning',
  DARK = 'dark',
  LIGHT = 'light'
}

2.2 武器实例类

class Weapon {
  private data: WeaponData;
  private currentCooldown: number = 0;
  private isCharging: boolean = false;
  private chargeTime: number = 0;
  
  constructor(data: WeaponData) {
    this.data = data;
  }
  
  get id(): string { return this.data.id; }
  get name(): string { return this.data.name; }
  get type(): WeaponType { return this.data.type; }
  get rarity(): WeaponRarity { return this.data.rarity; }
  get attackPower(): number { return this.data.attackPower; }
  get attackSpeed(): number { return this.data.attackSpeed; }
  get range(): number { return this.data.range; }
  get criticalRate(): number { return this.data.criticalRate; }
  get criticalDamage(): number { return this.data.criticalDamage; }
  
  isReady(): boolean {
    return this.currentCooldown <= 0;
  }
  
  startCooldown(): void {
    this.currentCooldown = this.data.attackSpeed;
  }
  
  updateCooldown(deltaTime: number): void {
    if (this.currentCooldown > 0) {
      this.currentCooldown -= deltaTime;
    }
  }
  
  startCharge(): void {
    this.isCharging = true;
    this.chargeTime = 0;
  }
  
  updateCharge(deltaTime: number): number {
    if (this.isCharging) {
      this.chargeTime += deltaTime;
      return Math.min(this.chargeTime / 1000, 1); // 最大蓄力1秒
    }
    return 0;
  }
  
  releaseCharge(): void {
    this.isCharging = false;
    this.chargeTime = 0;
  }
  
  getChargeLevel(): number {
    return this.chargeTime;
  }
}

三、武器攻击模式

3.1 攻击模式定义

攻击模式 描述 蓄力需求 伤害倍率
普通攻击 基础攻击 1.0x
蓄力攻击 蓄力后释放 0.5-1秒 1.5x-2.5x
技能攻击 特殊技能 冷却时间 3.0x

3.2 攻击状态机

enum AttackState {
  IDLE = 'idle',           // 空闲状态
  CHARGING = 'charging',   // 蓄力中
  ATTACKING = 'attacking', // 攻击中
  COOLDOWN = 'cooldown'    // 冷却中
}

class AttackController {
  private state: AttackState = AttackState.IDLE;
  private weapon: Weapon;
  private chargeStartTime: number = 0;
  private maxChargeTime: number = 1000; // 最大蓄力时间
  
  constructor(weapon: Weapon) {
    this.weapon = weapon;
  }
  
  handleAttackInput(inputType: 'press' | 'hold' | 'release'): AttackResult | null {
    switch (this.state) {
      case AttackState.IDLE:
        if (inputType === 'press') {
          this.startCharge();
        }
        break;
        
      case AttackState.CHARGING:
        if (inputType === 'release') {
          return this.executeAttack();
        } else if (inputType === 'hold') {
          this.updateCharge();
        }
        break;
        
      case AttackState.ATTACKING:
        // 攻击动画中,忽略输入
        break;
        
      case AttackState.COOLDOWN:
        if (this.weapon.isReady()) {
          this.state = AttackState.IDLE;
        }
        break;
    }
    return null;
  }
  
  private startCharge(): void {
    this.state = AttackState.CHARGING;
    this.chargeStartTime = Date.now();
    this.weapon.startCharge();
  }
  
  private updateCharge(): void {
    const chargeProgress = this.weapon.updateCharge(16); // 每帧更新
    // 可以根据蓄力进度显示不同的视觉效果
    this.updateChargeVisual(chargeProgress);
  }
  
  private executeAttack(): AttackResult {
    const chargeLevel = this.weapon.getChargeLevel();
    this.weapon.releaseCharge();
    this.weapon.startCooldown();
    
    const attackResult = this.calculateDamage(chargeLevel);
    this.state = AttackState.ATTACKING;
    
    // 启动攻击动画
    this.playAttackAnimation(chargeLevel);
    
    // 延迟后进入冷却状态
    setTimeout(() => {
      this.state = AttackState.COOLDOWN;
    }, 300); // 攻击动画时长
    
    return attackResult;
  }
  
  private calculateDamage(chargeLevel: number): AttackResult {
    // 基础伤害
    let damage = this.weapon.attackPower;
    
    // 蓄力加成:0.5秒1.5倍,1秒2.5倍
    const chargeMultiplier = 1 + chargeLevel * 1.5;
    damage *= chargeMultiplier;
    
    // 暴击判定
    const isCritical = Math.random() < this.weapon.criticalRate;
    if (isCritical) {
      damage *= this.weapon.criticalDamage;
    }
    
    // 元素伤害
    if (this.weapon.data.elementType && this.weapon.data.elementPower) {
      damage += this.weapon.data.elementPower * chargeLevel;
    }
    
    return {
      damage: Math.floor(damage),
      isCritical,
      chargeLevel,
      elementType: this.weapon.data.elementType
    };
  }
  
  private updateChargeVisual(progress: number): void {
    // 更新蓄力UI显示
    // 例如:蓄力条、武器发光效果等
  }
  
  private playAttackAnimation(chargeLevel: number): void {
    // 播放攻击动画
    // 根据蓄力等级播放不同强度的动画
  }
  
  update(deltaTime: number): void {
    this.weapon.updateCooldown(deltaTime);
    
    if (this.state === AttackState.COOLDOWN && this.weapon.isReady()) {
      this.state = AttackState.IDLE;
    }
  }
}

interface AttackResult {
  damage: number;
  isCritical: boolean;
  chargeLevel: number;
  elementType?: ElementType;
}

四、武器视觉效果系统

4.1 武器渲染组件

@Builder
buildWeapon(weapon: Weapon, isCharging: boolean, chargeLevel: number) {
  Stack({ alignContent: Alignment.Center }) {
    // 武器本体
    this.buildWeaponBody(weapon);
    
    // 蓄力光效
    if (isCharging) {
      this.buildChargeEffect(chargeLevel);
    }
    
    // 攻击特效
    if (this.isAttacking) {
      this.buildAttackEffect();
    }
  }
}

@Builder
buildWeaponBody(weapon: Weapon) {
  // 根据武器类型渲染不同的外观
  switch (weapon.type) {
    case WeaponType.MELEE:
      this.buildMeleeWeapon();
      break;
    case WeaponType.RANGED:
      this.buildRangedWeapon();
      break;
    case WeaponType.MAGIC:
      this.buildMagicWeapon();
      break;
  }
}

@Builder
buildMeleeWeapon() {
  // 近战武器:剑
  Column({ space: 0 }) {
    // 剑柄
    Rect()
      .width(8)
      .height(40)
      .fill('#8B4513');
    
    // 剑身
    Stack({ alignContent: Alignment.Bottom }) {
      Rect()
        .width(4)
        .height(60)
        .fill('#C0C0C0');
      
      // 剑刃
      Triangle()
        .width(0)
        .height(20)
        .fill('#E8E8E8')
        .translate({ x: 2, y: -60 });
    }
  }
}

@Builder
buildRangedWeapon() {
  // 远程武器:弓箭
  Stack() {
    // 弓身
    Ellipse()
      .width(60)
      .height(30)
      .fill('transparent')
      .border({ width: 4, color: '#8B4513' });
    
    // 弓弦
    Line()
      .width(60)
      .height(2)
      .stroke('#D2691E');
    
    // 箭矢
    if (this.hasArrow) {
      Column() {
        Triangle()
          .width(0)
          .height(15)
          .fill('#654321');
        Rect()
          .width(3)
          .height(30)
          .fill('#C0C0C0');
      }
      .translate({ y: -20 });
    }
  }
}

@Builder
buildMagicWeapon() {
  // 魔法武器:法杖
  Column({ space: 0 }) {
    // 杖柄
    Rect()
      .width(6)
      .height(80)
      .fill('#6B8E23');
    
    // 魔法水晶
    Stack({ alignContent: Alignment.Center }) {
      Circle()
        .width(25)
        .height(25)
        .fill('#9333EA')
        .blur(3);
      
      Circle()
        .width(15)
        .height(15)
        .fill('#C084FC');
    }
    .translate({ y: -5 });
  }
}

4.2 蓄力特效

@Builder
buildChargeEffect(chargeLevel: number) {
  // 蓄力光环
  Stack({ alignContent: Alignment.Center }) {
    // 外层光晕
    Circle()
      .width(40 + chargeLevel * 20)
      .height(40 + chargeLevel * 20)
      .fill(`rgba(255, 200, 0, ${0.2 + chargeLevel * 0.3})`)
      .blur(10 + chargeLevel * 5);
    
    // 中层光环
    Circle()
      .width(25 + chargeLevel * 10)
      .height(25 + chargeLevel * 10)
      .fill(`rgba(255, 255, 0, ${0.3 + chargeLevel * 0.4})`)
      .blur(5);
    
    // 内层闪烁
    Circle()
      .width(10)
      .height(10)
      .fill(`rgba(255, 255, 255, ${0.5 + chargeLevel * 0.5})`);
  }
}

五、伤害计算系统

5.1 伤害公式

class DamageCalculator {
  static calculate(baseDamage: number, attacker: Combatant, defender: Combatant): DamageResult {
    let finalDamage = baseDamage;
    
    // 攻击力加成
    finalDamage += attacker.attackPower * 0.1;
    
    // 防御力减免
    const defenseReduction = defender.defense * 0.05;
    finalDamage *= (1 - Math.min(defenseReduction, 0.8));
    
    // 元素克制
    if (attacker.elementType && defender.elementType) {
      const multiplier = this.getElementMultiplier(attacker.elementType, defender.elementType);
      finalDamage *= multiplier;
    }
    
    // 暴击判定
    const isCritical = Math.random() < attacker.criticalRate;
    if (isCritical) {
      finalDamage *= attacker.criticalDamage;
    }
    
    // 随机波动 ±5%
    finalDamage *= (0.95 + Math.random() * 0.1);
    
    return {
      damage: Math.max(1, Math.floor(finalDamage)),
      isCritical,
      elementType: attacker.elementType
    };
  }
  
  static getElementMultiplier(attackElement: ElementType, defenseElement: ElementType): number {
    const chart: Record<string, Record<string, number>> = {
      [ElementType.FIRE]: {
        [ElementType.FIRE]: 1.0,
        [ElementType.ICE]: 0.5,
        [ElementType.LIGHTNING]: 1.2,
        [ElementType.DARK]: 1.0,
        [ElementType.LIGHT]: 1.0
      },
      [ElementType.ICE]: {
        [ElementType.FIRE]: 1.2,
        [ElementType.ICE]: 1.0,
        [ElementType.LIGHTNING]: 0.5,
        [ElementType.DARK]: 1.0,
        [ElementType.LIGHT]: 1.0
      },
      // ... 其他元素组合
    };
    return chart[attackElement]?.[defenseElement] || 1.0;
  }
}

interface DamageResult {
  damage: number;
  isCritical: boolean;
  elementType?: ElementType;
}

interface Combatant {
  attackPower: number;
  defense: number;
  criticalRate: number;
  criticalDamage: number;
  elementType?: ElementType;
}

5.2 伤害数字显示

@Builder
buildDamageNumber(damage: number, isCritical: boolean, position: Position) {
  Stack({ alignContent: Alignment.Center }) {
    Text(damage.toString())
      .fontSize(isCritical ? 28 : 22)
      .fontWeight(FontWeight.Bold)
      .fontColor(isCritical ? '#FFD700' : '#FFFFFF')
      .textShadow({ radius: 10, color: isCritical ? '#FF8C00' : '#000000' })
      .animateTo({
        duration: 800,
        curve: Curve.EaseOut,
        translations: { y: -80 }
      });
    
    if (isCritical) {
      Text('暴击!')
        .fontSize(14)
        .fontColor('#FFD700')
        .translate({ y: 20 });
    }
  }
  .translate({ x: position.x, y: position.y });
}

六、武器装备与切换

6.1 装备管理

class WeaponInventory {
  private weapons: Array<Weapon> = [];
  private currentIndex: number = 0;
  
  addWeapon(weapon: Weapon): void {
    this.weapons.push(weapon);
  }
  
  removeWeapon(weaponId: string): void {
    this.weapons = this.weapons.filter(w => w.id !== weaponId);
    if (this.currentIndex >= this.weapons.length) {
      this.currentIndex = Math.max(0, this.weapons.length - 1);
    }
  }
  
  getCurrentWeapon(): Weapon | null {
    return this.weapons[this.currentIndex] || null;
  }
  
  switchToNext(): Weapon | null {
    if (this.weapons.length === 0) return null;
    this.currentIndex = (this.currentIndex + 1) % this.weapons.length;
    return this.weapons[this.currentIndex];
  }
  
  switchToPrevious(): Weapon | null {
    if (this.weapons.length === 0) return null;
    this.currentIndex = (this.currentIndex - 1 + this.weapons.length) % this.weapons.length;
    return this.weapons[this.currentIndex];
  }
  
  switchToIndex(index: number): Weapon | null {
    if (index < 0 || index >= this.weapons.length) return null;
    this.currentIndex = index;
    return this.weapons[this.currentIndex];
  }
  
  getWeaponCount(): number {
    return this.weapons.length;
  }
  
  getAllWeapons(): Array<Weapon> {
    return [...this.weapons];
  }
}

6.2 装备栏UI

@Builder
buildWeaponBar(inventory: WeaponInventory) {
  Row({ space: 10 }) {
    ForEach(inventory.getAllWeapons(), (weapon: Weapon, index: number) => {
      Stack({ alignContent: Alignment.Center }) {
        // 武器图标背景
        Circle()
          .width(50)
          .height(50)
          .fill(index === this.currentWeaponIndex 
            ? this.getRarityColor(weapon.rarity) 
            : 'rgba(255, 255, 255, 0.2)');
        
        // 武器图标
        this.buildWeaponIcon(weapon);
        
        // 选中指示器
        if (index === this.currentWeaponIndex) {
          Circle()
            .width(56)
            .height(56)
            .fill('transparent')
            .border({ width: 2, color: '#FFD700' });
        }
      }
      .onClick(() => {
        inventory.switchToIndex(index);
        this.currentWeaponIndex = index;
      });
    });
  }
  .padding({ top: 10, bottom: 10, left: 20, right: 20 })
  .backgroundColor('rgba(0, 0, 0, 0.5)')
  .borderRadius(15);
}

getRarityColor(rarity: WeaponRarity): string {
  switch (rarity) {
    case WeaponRarity.COMMON: return 'rgba(156, 163, 175, 0.5)';
    case WeaponRarity.UNCOMMON: return 'rgba(34, 197, 94, 0.5)';
    case WeaponRarity.RARE: return 'rgba(59, 130, 246, 0.5)';
    case WeaponRarity.EPIC: return 'rgba(168, 85, 247, 0.5)';
    case WeaponRarity.LEGENDARY: return 'rgba(251, 191, 36, 0.5)';
    default: return 'rgba(255, 255, 255, 0.2)';
  }
}

七、武器升级与强化

7.1 强化系统

class WeaponEnhancer {
  static enhance(weapon: Weapon, level: number): EnhancedWeapon {
    const enhancementBonus = 1 + level * 0.1; // 每级+10%
    
    return {
      ...weapon,
      attackPower: Math.floor(weapon.attackPower * enhancementBonus),
      criticalRate: Math.min(1, weapon.criticalRate + level * 0.02),
      enhanceLevel: level
    };
  }
  
  static calculateEnhanceCost(level: number): ResourceCost {
    return {
      gold: level * 100,
      materials: {
        'enhancement_stone': level * 2
      }
    };
  }
}

interface EnhancedWeapon extends Weapon {
  enhanceLevel: number;
}

interface ResourceCost {
  gold: number;
  materials: Record<string, number>;
}

7.2 附魔系统

class WeaponEnchanter {
  static enchant(weapon: Weapon, enchantment: Enchantment): EnchantedWeapon {
    return {
      ...weapon,
      enchantments: [...(weapon as EnchantedWeapon).enchantments || [], enchantment]
    };
  }
  
  static removeEnchantment(weapon: EnchantedWeapon, enchantmentId: string): EnchantedWeapon {
    return {
      ...weapon,
      enchantments: weapon.enchantments.filter(e => e.id !== enchantmentId)
    };
  }
}

interface Enchantment {
  id: string;
  name: string;
  effect: EnchantmentEffect;
  level: number;
}

interface EnchantmentEffect {
  type: 'damage' | 'speed' | 'critical' | 'element';
  value: number;
  elementType?: ElementType;
}

interface EnchantedWeapon extends Weapon {
  enchantments: Array<Enchantment>;
}

八、武器系统集成

8.1 战斗系统集成

class BattleSystem {
  private player: Player;
  private enemy: Enemy;
  private attackController: AttackController;
  
  constructor(player: Player, enemy: Enemy) {
    this.player = player;
    this.enemy = enemy;
    this.attackController = new AttackController(player.weapon);
  }
  
  handlePlayerInput(input: AttackInput): void {
    const result = this.attackController.handleAttackInput(input.type);
    
    if (result) {
      this.applyDamageToEnemy(result);
      this.updateBattleUI(result);
    }
  }
  
  private applyDamageToEnemy(result: AttackResult): void {
    const damageResult = DamageCalculator.calculate(
      result.damage,
      this.player,
      this.enemy
    );
    
    this.enemy.takeDamage(damageResult);
    
    // 显示伤害数字
    this.showDamageNumber(damageResult, this.enemy.position);
  }
  
  private updateBattleUI(result: AttackResult): void {
    // 更新玩家UI
    this.updatePlayerUI();
    
    // 更新敌人UI
    this.updateEnemyUI();
    
    // 检查战斗结束
    if (this.enemy.isDead) {
      this.onBattleEnd(true);
    }
  }
  
  update(deltaTime: number): void {
    this.attackController.update(deltaTime);
    this.player.update(deltaTime);
    this.enemy.update(deltaTime);
  }
}

interface AttackInput {
  type: 'press' | 'hold' | 'release';
  timestamp: number;
}

8.2 输入处理

// 键盘输入处理
handleKeyEvent(event: Object): void {
  let eventObj: Record<string, string | number> = event as Record<string, string | number>;
  let keyText: string = eventObj['keyText'] ? eventObj['keyText'] as string : '';
  let eventType: number = eventObj['type'] as number;
  
  // 攻击键
  if (keyText.toUpperCase() === 'U') {
    if (eventType === 1) { // 按下
      this.battleSystem.handlePlayerInput({ type: 'press', timestamp: Date.now() });
      this.attackHeld = true;
      
      // 长按检测
      setTimeout(() => {
        if (this.attackHeld) {
          this.battleSystem.handlePlayerInput({ type: 'hold', timestamp: Date.now() });
        }
      }, 100);
    } else if (eventType === 0) { // 释放
      this.attackHeld = false;
      this.battleSystem.handlePlayerInput({ type: 'release', timestamp: Date.now() });
    }
  }
  
  // 武器切换
  if (keyText.toUpperCase() === 'Q') {
    if (eventType === 1) {
      this.weaponInventory.switchToPrevious();
    }
  }
  
  if (keyText.toUpperCase() === 'E') {
    if (eventType === 1) {
      this.weaponInventory.switchToNext();
    }
  }
}

九、性能优化策略

9.1 渲染优化

优化项 实现方式 效果
对象池 复用武器特效对象 减少内存分配
条件渲染 只渲染激活状态的武器 减少渲染调用
层级合并 将武器与角色合并渲染 减少绘制批次
GPU加速 使用transform属性 硬件加速渲染

9.2 计算优化

// 伤害计算缓存
class DamageCache {
  private cache: Map<string, number> = new Map();
  
  getCachedDamage(attacker: Combatant, defender: Combatant): number | null {
    const key = this.generateKey(attacker, defender);
    return this.cache.get(key) || null;
  }
  
  cacheDamage(attacker: Combatant, defender: Combatant, damage: number): void {
    const key = this.generateKey(attacker, defender);
    this.cache.set(key, damage);
  }
  
  private generateKey(attacker: Combatant, defender: Combatant): string {
    return `${attacker.attackPower}-${attacker.criticalRate}-${defender.defense}`;
  }
}

十、扩展功能建议

10.1 可扩展功能

功能 描述 实现复杂度
武器熟练度 使用武器提升熟练度,解锁特殊技能
武器套装 收集套装获得额外加成
武器进化 武器升级进化为更高级形态
自定义武器 玩家自定义武器外观和属性
武器皮肤 更换武器外观皮肤

10.2 平衡性调整

// 难度调整
class WeaponBalancer {
  static adjustForDifficulty(weapon: Weapon, difficulty: GameDifficulty): Weapon {
    const multiplier = this.getDifficultyMultiplier(difficulty);
    
    return {
      ...weapon,
      attackPower: Math.floor(weapon.attackPower * multiplier),
      attackSpeed: Math.floor(weapon.attackSpeed / multiplier)
    };
  }
  
  private static getDifficultyMultiplier(difficulty: GameDifficulty): number {
    switch (difficulty) {
      case GameDifficulty.EASY: return 1.2;
      case GameDifficulty.NORMAL: return 1.0;
      case GameDifficulty.HARD: return 0.8;
      case GameDifficulty.NIGHTMARE: return 0.6;
      default: return 1.0;
    }
  }
}

enum GameDifficulty {
  EASY = 'easy',
  NORMAL = 'normal',
  HARD = 'hard',
  NIGHTMARE = 'nightmare'
}

十一、总结

本武器系统实现了以下核心功能:

  1. 完整的武器数据模型:支持多种武器类型、品质、属性
  2. 灵活的攻击模式:普通攻击、蓄力攻击、技能攻击
  3. 精美的视觉效果:武器外观、蓄力光效、伤害数字
  4. 精确的伤害计算:基础伤害、暴击、元素克制
  5. 便捷的装备管理:武器切换、装备栏UI
  6. 可扩展的强化系统:升级、附魔、进阶

系统设计遵循模块化原则,各组件职责清晰,便于后续扩展和维护。


技术栈:HarmonyOS 6.1 / ArkTS / ArkUI

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐