21 KiB
建页资料库
这份文档存放建页时常用但不需要每次都手写的信息:组件用法、常用图片名、配置片段。
1. 常用组件用法
1.1 BackgroundLayer
用途:长页面背景分段渲染,适合 bg0/bg1/bg2/bg3 这类长活动页。
<BackgroundLayer :backgroundImages="[imageUrl('bg0'), imageUrl('bg1'), imageUrl('bg2')]" />
1.2 itemCenter
用途:背景图 + 内部绝对定位内容,是活动页最常用的图片容器。
<itemCenter
:imgUrl="imageUrl('rewardBg')"
style="width: 100vw; min-height: 21vw; max-height: 22vw"
contentStyle="padding: 10vw 6vw;"
>
<!-- 内容 -->
</itemCenter>
开发完成后需要稳定图片容器高度时,按图片比例补 min-height,并同步补接近的 max-height,一般可用 max-height = min-height + 1vw,避免图片加载出来之前容器异常撑高。
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/Activities 和 src/views/Ranking 中常见的 imageUrl('xxx')、webpUrl('xxx')、getImgName('xxx') 用法。新页面不需要全部准备,按模块挑选即可。
注意:图片名大小写必须和文件名一致。项目里已有一些历史命名,例如 RankingItem、RankingBottomBorder、rechargehidden,这里按现有代码保留。
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; 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 Rank 和 Room 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 分阶段图片预加载
用途:把首屏关键图片和后续图片拆开。首屏关键图片参与进入页面加载动画;弹窗、非默认标签页、下方长背景等图片在页面进入后后台继续预加载。
import { connectToApp } from '@/utils/appConnector.js'
// 进入页面前必须完成的图片,加载完成后再结束 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)
}
// 首屏预加载:只处理阻塞图片,不等待业务接口。
const completePreloading = async () => {
try {
await preloadBlockingImages()
} finally {
isLoading.value = false
preloadBackgroundImages()
}
}
// 页面初始化接口:连接 App 并写入请求头后,再单独拉取业务数据。
const loadInitialPageData = async () => {
// await getPageData()
}
// 连接 App:使用接口的页面必须在 connectToApp 成功回调后再发起业务接口请求。
const connectToAppHandler = async () => {
await connectToApp(() => {
loadInitialPageData()
})
}
onMounted(() => {
completePreloading()
connectToAppHandler()
})