aslan-h5/docs/活动页/建页/建页资料库.md

20 KiB
Raw Blame History

建页资料库

这份文档存放建页时常用但不需要每次都手写的信息:组件用法、常用图片名、配置片段。

1. 常用组件用法

1.1 BackgroundLayer

用途:长页面背景分段渲染,适合 bg0/bg1/bg2/bg3 这类长活动页。

<BackgroundLayer :backgroundImages="[imageUrl('bg0'), imageUrl('bg1'), imageUrl('bg2')]" />

1.2 itemCenter

用途:背景图 + 内部绝对定位内容,是活动页最常用的图片容器。

<itemCenter :imgUrl="imageUrl('rewardBg')" contentStyle="padding: 10vw 6vw;">
  <!-- 内容 -->
</itemCenter>

1.3 topUser / TopUser

用途:前三名用户展示。不同页面可能有自己的 components/topUser.vue,新页面可先从参考页面复制一份再微调。

<TopUser
  :avatarUrl="item.userAvatar"
  :name="item.userName"
  :distributionValue="item.amount"
/>
import TopUser from './components/topUser.vue'

1.4 Barrage

用途中奖用户、活动动态等弹幕。LuckyDollars 页面常用。

<Barrage :list="barrageList" />
import Barrage from './components/Barrage.vue'

1.5 ActivityTabs

用途:图片背景标签页。适合初始页面快速搭标签切换。

<ActivityTabs
  :bg-url="imageUrl('tagsBg')"
  :indicator-url="imageUrl('tagBtBg')"
  :tabs="visibleTabs"
  :active-value="currentTab"
  @change="changeTab"
/>

1.6 ActivityLotteryGrid

用途:抽奖格子、高亮框和中心按钮区域。不同抽奖背景只改 page.config.js 里的布局。

<ActivityLotteryGrid
  :prizes="prizeList"
  :slot-count="pageConfig.lottery.slotCount"
  :active-index="activeIndex"
  :active-frame-url="imageUrl('prizeActiveFrame')"
  :grid-style="pageConfig.lottery.grid.style"
  :position-map="pageConfig.lottery.grid.positionMap"
  :button-grid-area="pageConfig.lottery.grid.buttonGridArea"
  :prize-render-mode="pageConfig.lottery.prizeRenderMode"
  :disabled="isRolling"
  @draw="draw(1)"
/>

2. 常用图片名清单

下面的图片名来自 src/views/Activitiessrc/views/Ranking 中常见的 imageUrl('xxx')webpUrl('xxx')getImgName('xxx') 用法。新页面不需要全部准备,按模块挑选即可。

注意:图片名大小写必须和文件名一致。项目里已有一些历史命名,例如 RankingItemRankingBottomBorderrechargehidden,这里按现有代码保留。

2.1 页面背景和顶部

imageUrl('bg') // 页面主背景
imageUrl('bg0') // 页面背景第 0 段
imageUrl('bg1') // 页面背景第 1 段
imageUrl('bg2') // 页面背景第 2 段
imageUrl('bg3') // 页面背景第 3 段
webpUrl('pageTop') // 页面顶部 WebP 背景
imageUrl('timeBg') // 活动时间背景
imageUrl('dayBg') // 日期/天数背景
imageUrl('TimeBg') // 活动时间背景,历史大写命名

2.1.1 排行榜前几名展示区

推荐新页面使用 rankingTopBg,含义更明确:排行榜前几名展示区背景,不限定一定是前三名。

imageUrl('rankingTopBg') // 排行榜前几名展示区背景,推荐新命名
imageUrl('topBg') // 排行榜前几名展示区背景,历史命名,不再作为页面顶部背景理解
imageUrl('top1') // 第一名头像/排名装饰
imageUrl('top2') // 第二名头像/排名装饰
imageUrl('top3') // 第三名头像/排名装饰
imageUrl('top1Bg') // 第一名独立背景
imageUrl('top2Bg') // 第二名独立背景
imageUrl('top3Bg') // 第三名独立背景

2.2 标签页和按钮

imageUrl('tagsBg') // 标签页整体背景
imageUrl('tagBtBg') // 标签页选中底图
imageUrl(getImgName('rankBt')) // 排行榜未选中按钮
imageUrl(getImgName('rankBtActive')) // 排行榜选中按钮
imageUrl(getImgName('rankingBt')) // 排行按钮
imageUrl(getImgName('rankingBtActive')) // 排行选中按钮
imageUrl(getImgName('lotteryBt')) // 抽奖未选中按钮
imageUrl(getImgName('lotteryBtActive')) // 抽奖选中按钮
imageUrl(getImgName('rewardBt')) // 奖励未选中按钮
imageUrl(getImgName('rewardBtActive')) // 奖励选中按钮
imageUrl(getImgName('rechargeBt')) // 充值未选中按钮
imageUrl(getImgName('rechargeBtActive')) // 充值选中按钮
imageUrl(getImgName('redeemBt')) // 兑换按钮
imageUrl(getImgName('withdrawalBt')) // 提现未选中按钮
imageUrl(getImgName('withdrawalBtActive')) // 提现选中按钮

2.3 排行榜

imageUrl('RankingMain') // 排行榜主体背景
imageUrl('RankingItem') // 排行榜列表项背景
imageUrl('rankingItemBg') // 排行榜列表项背景,另一套命名
imageUrl('RankingTopBorder') // 排行榜顶部边框
imageUrl('RankingBottomBorder') // 排行榜底部边框
imageUrl('RankingBorder') // 排行榜通用边框
imageUrl('myRankingBg') // 我的排名固定栏背景
imageUrl('rankingNumBg') // 排名数字背景
imageUrl('rankingTopBg') // 排行榜前几名展示区背景,推荐新命名
imageUrl('topBg') // 排行榜前几名展示区背景,历史命名
imageUrl('top1') // 第一名头像/排名装饰
imageUrl('top2') // 第二名头像/排名装饰
imageUrl('top3') // 第三名头像/排名装饰
imageUrl('top1Bg') // 第一名独立背景
imageUrl('top2Bg') // 第二名独立背景
imageUrl('top3Bg') // 第三名独立背景
imageUrl('top1-charm') // 魅力榜第一名装饰
imageUrl('top2-charm') // 魅力榜第二名装饰
imageUrl('top3-charm') // 魅力榜第三名装饰
imageUrl('top1-wealth') // 财富榜第一名装饰
imageUrl('top2-wealth') // 财富榜第二名装饰
imageUrl('top3-wealth') // 财富榜第三名装饰
imageUrl('top1-room') // 房间榜第一名装饰
imageUrl('top2-room') // 房间榜第二名装饰
imageUrl('top3-room') // 房间榜第三名装饰
imageUrl('myRankingBg-charm') // 魅力榜我的排名背景
imageUrl('myRankingBg-wealth') // 财富榜我的排名背景
imageUrl('myRankingBg-room') // 房间榜我的排名背景
imageUrl('RankingItem-charm') // 魅力榜列表项背景
imageUrl('RankingItem-wealth') // 财富榜列表项背景
imageUrl('RankingItem-room') // 房间榜列表项背景
imageUrl('tabSelectedBg') // 榜单分类选中底图
imageUrl('rankingSeasonBt') // 赛季榜按钮
imageUrl('rankingSeasonBtActive') // 赛季榜选中按钮
imageUrl('rankingWeeklyBt') // 周榜按钮
imageUrl('rankingWeeklyBtActive') // 周榜选中按钮

2.4 抽奖

imageUrl('lottery') // 抽奖机/抽奖盘背景
imageUrl('lotteryBg') // 抽奖区域背景
imageUrl('prizeActiveFrame') // 抽奖高亮框
imageUrl('draw1BtBg') // 单抽按钮背景
imageUrl('draw5BtBg') // 五连抽按钮背景
imageUrl('draw10BtBg') // 十连抽按钮背景
imageUrl('resultBg') // 中奖结果弹窗背景
imageUrl('resultBack') // 中奖结果上一页按钮
imageUrl('resultNext') // 中奖结果下一页按钮
imageUrl('resultBt') // 中奖结果确认按钮
imageUrl('resultGoOnBt') // 继续抽奖按钮

2.5 奖励和奖品

imageUrl('rewardBg') // 奖励模块背景
imageUrl('reward_banner') // 奖励横幅
imageUrl('rewards') // 奖励集合图
imageUrl('rewardBack') // 奖励上一页按钮
imageUrl('rewardNext') // 奖励下一页按钮
imageUrl(getImgName('rewardReceive')) // 奖励领取按钮
imageUrl(getImgName('rewardReceived')) // 奖励已领取按钮
imageUrl(getImgName('rewardReceiveNot')) // 奖励不可领取按钮
imageUrl(getImgName('receiveBt')) // 领取按钮
imageUrl(getImgName('receivedBt')) // 已领取按钮
imageUrl('reward_gift') // 礼物奖励图标
imageUrl('reward_frame') // 头像框奖励图标
imageUrl('reward_ride') // 座驾奖励图标
imageUrl('ticket') // 抽奖券图标
imageUrl('crystal') // 水晶/活动货币图标
imageUrl('debris') // 碎片/道具图标
imageUrl('giftBg') // 礼物背景
imageUrl('giftItemBg') // 礼物列表项背景
imageUrl('RewardRecharge100') // 充值 100 奖励图
imageUrl('RewardRecharge500') // 充值 500 奖励图
imageUrl('RewardRecharge1000') // 充值 1000 奖励图
imageUrl('RewardRecharge3000') // 充值 3000 奖励图
imageUrl('RewardRecharge5000') // 充值 5000 奖励图
imageUrl('RewardRecharge10000') // 充值 10000 奖励图
imageUrl('rechargeReward100') // 充值 100 奖励图,另一套命名
imageUrl('rechargeReward500') // 充值 500 奖励图,另一套命名
imageUrl('rechargeReward1000') // 充值 1000 奖励图,另一套命名
imageUrl('rechargeReward3000') // 充值 3000 奖励图,另一套命名
imageUrl('rechargeReward5000') // 充值 5000 奖励图,另一套命名
imageUrl('rechargeReward10000') // 充值 10000 奖励图,另一套命名

2.6 任务

imageUrl('taskBtGo') // 任务去完成按钮
imageUrl('taskBtReceive') // 任务领取按钮
imageUrl('taskBtReceived') // 任务已领取按钮
imageUrl('taskGame') // 游戏任务图标
imageUrl('taskGift') // 送礼任务图标
imageUrl('taskRecharge') // 充值任务图标
imageUrl('taskTalk') // 聊天/上麦任务图标
imageUrl('taskItemBg') // 任务列表项背景
imageUrl('taskListBg') // 任务列表背景
imageUrl('taskTypeGame') // 游戏任务类型图标
imageUrl('taskTypeGift') // 礼物任务类型图标

2.7 弹窗、规则、帮助和历史

弹窗遮罩统一使用公共组件 src/components/MaskLayer.vue,不要在页面里重复手写固定定位遮罩、背景滚动锁定和滚动阻止逻辑。弹窗内容放入默认插槽;如果要点击空白关闭,在插槽内包一层全屏容器并绑定 @click.self

<MaskLayer :maskLayerShow="showPopup">
  <div
    style="width: 100vw; min-height: 100vh; display: flex; align-items: flex-start; justify-content: center; padding: 6vh 0 10vh; box-sizing: border-box;"
    @click.self="showPopup = false"
  >
    <!-- 弹窗内容模块使用 itemCenter 或普通 div 承载弹窗背景和内容 -->
  </div>
</MaskLayer>
imageUrl(getImgName('helpInfo')) // 帮助说明图片
imageUrl('helpBg') // 帮助弹窗背景
imageUrl('helpBt') // 帮助按钮
imageUrl(getImgName('ruleInfo')) // 规则说明图片
imageUrl('ruleInfoBg') // 规则弹窗背景
imageUrl(getImgName('ruleTitle')) // 规则标题图
imageUrl(getImgName('rulesBt')) // 规则按钮
imageUrl(getImgName('historyBt')) // 历史按钮
imageUrl(getImgName('historyBg')) // 历史弹窗背景
imageUrl('historyTopBg') // 历史弹窗顶部背景
imageUrl('recordBg') // 记录列表背景
imageUrl('closeBt') // 关闭按钮

2.8 用户信息、充值和收益

imageUrl('myInfoBg') // 我的信息背景
imageUrl('myAvatarFrame') // 我的头像框
imageUrl('userNameBorder') // 用户名边框
imageUrl('userFrame') // 用户头像框
imageUrl('earningInfoBg') // 收益信息背景
imageUrl('earningsBg') // 收益背景
imageUrl('distribution') // 分发/派奖图标
imageUrl('rechargehidden') // 充值金额隐藏图标
imageUrl('rechargeShow') // 充值金额显示图标
imageUrl('rechargeNumHidden') // 充值数字隐藏图标
imageUrl('rechargeNumShow') // 充值数字显示图标
imageUrl('amountHiddenBt') // 金额隐藏按钮
imageUrl('amountShowBt') // 金额显示按钮

2.9 游戏玩法和特殊模块

imageUrl('gameLotteryBt') // 游戏玩法-抽奖按钮
imageUrl('gameLotteryBtActive') // 游戏玩法-抽奖选中按钮
imageUrl('gameSignInBt') // 游戏玩法-签到按钮
imageUrl('gameSignInBtActive') // 游戏玩法-签到选中按钮
imageUrl('gameExchangeBt') // 游戏玩法-兑换按钮
imageUrl('gameExchangeBtActive') // 游戏玩法-兑换选中按钮
imageUrl('goodsItem') // 兑换商品项背景
imageUrl('makeUpBtBg') // 补签按钮背景
imageUrl('rewardGoodsBg') // 奖励物品背景
imageUrl('progressBar') // 进度条图片
imageUrl('timeBack') // 时间/日期上一页按钮
imageUrl('timeNext') // 时间/日期下一页按钮

3. 模块预设

这些预设用于创建“页面创建信息 md”时自动填充目标是少问、少填、先生成能跑的初版。图片字段优先从 3.1 多语言图片清单 中匹配;没有匹配到的图片名可以留空或标记待确认。

3.1 Activities 通用活动页

适用:src/views/Activities 下类似 LuckyDollars、LesserBairam、SpringFestival 的活动页。

{
  "reward": {
    "enabledWhenAnyImageExists": ["rewardBg", "rewardReceive", "rewardReceived", "rewardReceiveNot"],
    "apis": ["activityRewardConfigs", "myRecharge", "receiveRechargeReward"],
    "defaultImages": ["rewardBg", "rewardReceive", "rewardReceived", "rewardReceiveNot", "ticket", "reward_gift", "reward_frame", "reward_ride"],
    "remark": "充值/消费奖励模块"
  },
  "ranking": {
    "enabledWhenAnyImageExists": ["RankingItem", "myRankingBg", "rankingTopBg", "topBg", "top1", "top2", "top3", "rankBt", "rankBtActive"],
    "apis": ["ranklist"],
    "loadMode": "remote",
    "pageSize": 20,
    "topCount": 3,
    "myRankingPath": "ranklist.body.currentUser",
    "fieldMap": {
      "avatar": "userAvatar",
      "name": "userName",
      "value": "amount",
      "userId": "userId",
      "rank": "rank"
    },
    "defaultImages": ["RankingItem", "myRankingBg", "rankingTopBg", "top1", "top2", "top3"],
    "remark": "活动内排行榜,常见为接口分页"
  },
  "lottery": {
    "enabledWhenAnyImageExists": ["lottery", "lotteryBg", "prizeActiveFrame", "lotteryBt", "lotteryBtActive"],
    "drawApis": ["onceDraw", "multiDraw"],
    "prizePoolApi": "activityDetail",
    "drawCountApi": "myTickets",
    "extraApis": ["myTotalDrawCount", "rewardConfigsBadge", "winnerHistory"],
    "historyApi": "drawRecords",
    "displayMode": "track-only",
    "slotCount": 8,
    "historyButtonPosition": "inside",
    "defaultImages": {
      "background": "lottery",
      "activeFrame": "prizeActiveFrame",
      "historyButton": "historyBt",
      "resultBackground": "resultBg"
    },
    "remark": "抽奖接口基本固定;奖品展示方式按页面图片调整"
  },
  "task": {
    "enabledWhenAnyImageExists": ["taskBtGo", "taskBtReceive", "taskBtReceived", "taskGame", "taskGift", "taskRecharge", "taskTalk"],
    "apis": ["ActTaskList", "receiveTickets"],
    "defaultImages": ["taskBtGo", "taskBtReceive", "taskBtReceived", "taskGame", "taskGift", "taskRecharge", "taskTalk"],
    "remark": "任务列表和任务领奖"
  },
  "withdraw": {
    "enabledWhenAnyImageExists": ["earningInfoBg", "myInfoBg"],
    "apis": ["withdrawableAmount", "transferActivityDollar", "exchangeCoin"],
    "defaultImages": ["earningInfoBg", "myInfoBg"],
    "remark": "提现、转账或兑换模块"
  },
  "popups": {
    "rule": {
      "enabledWhenAnyImageExists": ["rulesBt", "ruleInfo"],
      "triggerImage": "rulesBt",
      "contentImage": "ruleInfo"
    },
    "help": {
      "enabledWhenAnyImageExists": ["helpBt", "helpInfo"],
      "triggerImage": "helpBt",
      "contentImage": "helpInfo"
    },
    "history": {
      "enabledWhenAnyImageExists": ["historyBt", "historyBg"],
      "triggerImage": "historyBt",
      "backgroundImage": "historyBg",
      "apis": ["drawRecords"]
    }
  }
}

3.2 Ranking 独立排行榜页

适用:src/views/Ranking 下独立排行榜页。这里要特别区分加载方式:

  • remote:接口支持 pageNo/pageSize,上拉时继续请求下一页。
  • local:接口一次返回完整榜单,前端先展示一段,上拉时 slice 下一段,例如 src/views/Ranking/Overall/Ranking.vue
{
  "ranking": {
    "loadMode": "local / remote",
    "topCount": 3,
    "pageSize": 10,
    "fieldMap": {
      "avatar": "avatar",
      "name": "nickname",
      "value": "quantityFormat",
      "userId": "id",
      "rank": "rank"
    },
    "commonImages": [
      "RankingItem",
      "myRankingBg",
      "top1",
      "top2",
      "top3",
      "tabSelectedBg"
    ],
    "remark": "如果接口差异不明确,先问用户参考哪个 Ranking 页面"
  }
}

3.3 什么时候需要问用户

同一模块存在多个接口版本时,问参考页面。
抽奖模块不是 8 格或不是 track-only 时,问抽奖展示方式。
排行榜接口不知道是 remote 还是 local 时,问参考页面或看接口是否传 pageNo/pageSize。
图片名看不出用途且无法从参考页面推断时,标记待确认,不阻塞初版生成。

4. 页面配置片段

4.1 图片工具

import { useActivityAssets } from '@/composables/activity/useActivityAssets.js'
import { pageConfig } from './page.config.js'

const currentLangType = computed(() => {
  return langStore.selectedLang?.type || 'en'
})

const { imageUrl, webpUrl, getImageName: getImgName } = useActivityAssets(
  pageConfig,
  currentLangType,
)

4.2 标签页

import { useActivityTabs } from '@/composables/activity/useActivityTabs.js'

const { currentTab, visibleTabs, isTab, changeTab } = useActivityTabs(pageConfig.tabs, {
  translate: t,
})

4.2.1 嵌套标签 children

用途:描述“一级标签下还有二级标签/子区块”的页面结构,例如 Gulben Festival 的 Personal RankRoom Rank 下再分 Reward / Ranking

推荐配置形态:

modules: {
  tabs: {
    enabled: true,
    defaultValue: 'Personal Rank',
    items: ['CollectCards to Win Prizes', 'Personal Rank', 'Room Rank'],
  },
  sections: [
    {
      name: 'personalRank',
      enabled: true,
      images: ['tagActiveBg', 'tagBg'],
      children: {
        tabs: {
          enabled: true,
          defaultValue: 'Reward',
          items: ['Reward', 'Ranking'],
        },
        sections: [
          {
            name: 'Reward',
            enabled: true,
            images: ['moduleActiveBg', 'moduleBg'],
            children: {},
          },
          {
            name: 'Ranking',
            enabled: true,
            images: ['moduleActiveBg', 'moduleBg'],
            children: {},
          },
        ],
      },
    },
  ],
}

生成规则:

children 为空对象时,不生成子标签。
children.tabs 控制当前 section 内部的二级标签状态。
children.sections 控制当前 section 内部的二级内容。
children.tabs.defaultValue 必须能匹配 children.sections 里的 name/value。
items 是字符串时,直接用字符串作为 value 和显示文本items 是对象时,优先使用 value、label、labelKey、buttonImage、activeButtonImage。
备注写明“开发期间不加翻译”时,页面直接展示 md 里的英文文本。
标签图片为背景时,优先用 itemCenter 或等价图片容器承载文本,不把整段文字做成图片。

4.3 排行榜

import { useActivityRanking } from '@/composables/activity/useActivityRanking.js'

const rankingState = useActivityRanking({
  loadMode: pageConfig.ranking.loadMode,
  pageSize: pageConfig.ranking.pageSize,
  topCount: pageConfig.ranking.topCount,
  fetchPage: ({ pageNo, pageSize }) => {
    return ranklist({
      activityId: pageConfig.activity.activityId,
      pageNo,
      pageSize,
    })
  },
})

4.4 抽奖

import { useLotteryDraw } from '@/composables/activity/useLotteryDraw.js'

const { activeIndex, isRolling, startLottery } = useLotteryDraw({
  getSlotCount: () => prizeList.value.length || pageConfig.lottery.slotCount,
})

4.5 分阶段图片预加载

用途:把首屏关键图片和后续图片拆开。首屏关键图片参与进入页面加载动画;弹窗、非默认标签页、下方长背景等图片在页面进入后后台继续预加载。

// 进入页面前必须完成的图片,加载完成后再结束 loading 动画。
const blockingPreloadImageNames = pageConfig.preload?.blocking || []

// 进入页面后继续后台加载的图片,不阻塞页面展示。
const backgroundPreloadImageNames = pageConfig.preload?.background || []

// 统一走 imageUrl 和 getImgName保证本地 OSS、线上 OSS、缓存版本、多语言后缀规则一致。
const resolvePreloadUrls = (names = []) => {
  return [...new Set(names)].map((name) => imageUrl(getImgName(name)))
}

const preloadImageList = (urls = []) => {
  return Promise.all(
    urls.map((url) => new Promise((resolve) => {
      const img = new Image()
      img.onload = resolve
      img.onerror = resolve
      img.src = url
    })),
  )
}

const preloadBlockingImages = async () => {
  await preloadImageList(resolvePreloadUrls(blockingPreloadImageNames))
}

const preloadBackgroundImages = () => {
  const urls = resolvePreloadUrls(backgroundPreloadImageNames)
  if (!urls.length) return

  // 后台预加载不影响当前页面展示,所以失败也只吞掉。
  const run = () => preloadImageList(urls).catch(() => {})
  if (window.requestIdleCallback) {
    window.requestIdleCallback(run)
    return
  }
  setTimeout(run, 0)
}

onMounted(async () => {
  await preloadBlockingImages()
  isLoading.value = false
  preloadBackgroundImages()
})