feat(listing): 发布新增「是否解锁德穆兰」必填项,首页优先替换全英雄展示

This commit is contained in:
yml2213
2026-10-16 13:07:25 +08:00
parent b7b68abf6b
commit 703deb17d0
8 changed files with 73 additions and 2 deletions
@@ -99,6 +99,7 @@ const primaryRows = computed(() => {
{ label: '常用登录地', value: regions.length ? regions.join('、') : '--' },
{ label: '人脸归属', value: formatScalar(a.face_owner) },
{ label: '是否可以修改游戏名', value: formatScalar(a.can_change_game_name) },
{ label: '是否解锁德穆兰', value: formatScalar(a.unlock_demulan) },
{
label: '封禁记录',
value: formatScalar(a.ban_record) === '--' ? '无' : formatScalar(a.ban_record),
@@ -142,6 +143,7 @@ const extraRows = computed(() => {
'screenshot_groups',
'online_time',
'can_change_game_name',
'unlock_demulan',
'unlock_said',
'ban_record',
'common_regions',
@@ -20,6 +20,7 @@ export function defaultPublishForm(): PublishForm {
early_morning_response: '否',
can_change_game_name: '',
all_hero: '',
unlock_demulan: '',
next_season_pass: '',
ban_record: '',
common_regions: [],
@@ -320,6 +320,7 @@ export function usePublishForm(options: UsePublishFormOptions) {
early_morning_response: stringValue(summary.early_morning_response) || '否',
can_change_game_name: stringValue(summary.can_change_game_name),
all_hero: stringValue(summary.all_hero),
unlock_demulan: stringValue(summary.unlock_demulan),
next_season_pass: stringValue(summary.next_season_pass),
ban_record: stringValue(summary.ban_record),
common_regions: stringArray(summary.common_regions),
@@ -733,6 +734,7 @@ export function usePublishForm(options: UsePublishFormOptions) {
if (pricing.banRecordOptions.value.length && !form.ban_record) return '请选择封禁记录'
if (!form.can_change_game_name) return '请选择是否可以修改游戏名'
if (!form.all_hero) return '请选择是否有全英雄'
if (!form.unlock_demulan) return '请选择是否解锁德穆兰'
if (nextSeasonPassEnabled.value && !form.next_season_pass) {
return '请选择下赛季是否购买通行证'
}
@@ -838,6 +840,7 @@ export function usePublishForm(options: UsePublishFormOptions) {
early_morning_response: form.early_morning_response,
can_change_game_name: form.can_change_game_name,
all_hero: form.all_hero,
unlock_demulan: form.unlock_demulan,
next_season_pass: form.next_season_pass,
ban_record: form.ban_record,
common_regions: form.common_regions,
@@ -123,6 +123,7 @@ function selectRadio<T extends string>(value: T, setter: (value: T) => void) {
const canChangeGameNameOptions = ['是', '否']
const allHeroOptions = ['是', '否']
const demulanUnlockOptions = ['是', '否']
const nextSeasonPassOptions = ['购买', '不购买']
const earlyMorningResponseOptions = ['是', '否']
@@ -443,6 +444,23 @@ const screenshotGuides: Record<string, string> = {
</template>
</van-field>
<van-field label="是否解锁德穆兰" required class="publish-field">
<template #input>
<div class="radio-group">
<button
v-for="opt in demulanUnlockOptions"
:key="opt"
type="button"
class="radio-btn"
:class="{ active: form.unlock_demulan === opt }"
@click="selectRadio(opt, value => (form.unlock_demulan = value))"
>
{{ opt }}
</button>
</div>
</template>
</van-field>
<van-field
v-if="nextSeasonPassEnabled"
label="下赛季是否购买通行证"
@@ -122,6 +122,7 @@ const activeAgreementContent = computed(() => activeAgreement.value?.content ||
const canChangeGameNameOptions = ['是', '否']
const allHeroOptions = ['是', '否']
const demulanUnlockOptions = ['是', '否']
const nextSeasonPassOptions = ['购买', '不购买']
const earlyMorningResponseOptions = ['是', '否']
@@ -359,6 +360,15 @@ function selectDailyLoss(value: string | number) {
/>
</div>
<div class="field-row panel-field-row">
<label>是否解锁德穆兰<span>*</span></label>
<OptionChips
:options="demulanUnlockOptions"
:model-value="form.unlock_demulan"
@select="form.unlock_demulan = String($event)"
/>
</div>
<div v-if="nextSeasonPassEnabled" class="field-row panel-field-row">
<label>下赛季是否购买通行证<span>*</span></label>
<OptionChips
+2
View File
@@ -21,6 +21,8 @@ export type PublishForm = {
can_change_game_name: string
/** 是否有全英雄(是/否) */
all_hero: string
/** 是否解锁德穆兰(是/否);为「是」时首页展示替换「全英雄」 */
unlock_demulan: string
/** 下赛季是否购买通行证(购买/不购买) */
next_season_pass: string
ban_record: string
@@ -82,3 +82,35 @@ describe('首页规格芯片', () => {
expect(missing).toBeUndefined()
})
})
describe('首页规格芯片 · 德穆兰优先级高于全英雄', () => {
it('解锁德穆兰时用「解锁德穆兰」替换「全英雄」', () => {
const chips = getListingChips(buildListing({ all_hero: '是', unlock_demulan: '是' }))
expect(chips.find(chip => chip.label === '解锁德穆兰')).toEqual({
label: '解锁德穆兰',
value: '是',
})
expect(chips.find(chip => chip.label === '全英雄')).toBeUndefined()
})
it('未解锁德穆兰时保持原有全英雄展示逻辑', () => {
const chips = getListingChips(buildListing({ all_hero: '是', unlock_demulan: '否' }))
expect(chips.find(chip => chip.label === '全英雄')).toEqual({ label: '全英雄', value: '是' })
expect(chips.find(chip => chip.label === '解锁德穆兰')).toBeUndefined()
})
it('未解锁德穆兰且无全英雄时两者都不展示', () => {
const chips = getListingChips(buildListing({ all_hero: '否', unlock_demulan: '否' }))
expect(chips.find(chip => chip.label === '全英雄')).toBeUndefined()
expect(chips.find(chip => chip.label === '解锁德穆兰')).toBeUndefined()
})
it('老数据缺少德穆兰字段时沿用全英雄展示', () => {
const chips = getListingChips(buildListing({ all_hero: '是' }))
expect(chips.find(chip => chip.label === '全英雄')).toEqual({ label: '全英雄', value: '是' })
})
})
+5 -2
View File
@@ -160,8 +160,11 @@ export function getListingChips(item: PublicListingItem): ListingDisplayChip[] {
if (canChangeGameName === '是' || canChangeGameName === '否') {
chips.push({ label: '可修改游戏名', value: canChangeGameName })
}
// 全英雄为必选项,仅在号主勾选「是」时展示
if (readAssetString(item, 'all_hero') === '是') {
// 全英雄为必选项,仅在号主勾选「是」时展示;解锁德穆兰展示优先级更高,命中时替换「全英雄」。
const allHero = readAssetString(item, 'all_hero')
if (readAssetString(item, 'unlock_demulan') === '是') {
chips.push({ label: '解锁德穆兰', value: '是' })
} else if (allHero === '是') {
chips.push({ label: '全英雄', value: '是' })
}
const nextSeasonPass = readAssetString(item, 'next_season_pass')