199 lines
6.4 KiB
TypeScript
199 lines
6.4 KiB
TypeScript
import { asyncComputed } from '@vueuse/core'
|
|
import api from '@/api'
|
|
import './style.scss'
|
|
import { UiDataSection } from '@/components/ui/data-section'
|
|
import { TabsRoot, UiTabsList, UiTabsTrigger } from '@/components/ui/tabs'
|
|
|
|
export default defineComponent({
|
|
name: 'SkillDetail',
|
|
props: {
|
|
skillId: {
|
|
type: String,
|
|
required: true,
|
|
},
|
|
level: {
|
|
type: Number,
|
|
default: 1,
|
|
},
|
|
},
|
|
setup(props) {
|
|
const currentSkill = computed(() => props.skillId)
|
|
const currentLevel = computed(() => props.level)
|
|
|
|
const skillInfo = asyncComputed(async () => {
|
|
if (!currentSkill.value && !currentLevel.value) return undefined
|
|
const res = await api.skillDetail(currentSkill.value, currentLevel.value)
|
|
return res
|
|
})
|
|
|
|
const curTab = ref(0)
|
|
|
|
const basic = computed(() =>
|
|
!skillInfo.value
|
|
? []
|
|
: [
|
|
{ label: '技能等级', value: skillInfo.value?.attribute?.level ?? props.level },
|
|
{ label: '学习等级', value: skillInfo.value?.requiredLevel },
|
|
{ label: '等级上限', value: skillInfo.value?.maxLevel },
|
|
{
|
|
label: '冷却时间',
|
|
value: skillInfo.value?.attribute?.coolTime
|
|
? `${skillInfo.value?.attribute?.coolTime.toFixed(1)}秒`
|
|
: undefined,
|
|
},
|
|
{
|
|
label: '施放时间',
|
|
value: !skillInfo.value?.attribute?.castingTime
|
|
? '瞬发'
|
|
: `${skillInfo.value?.attribute?.castingTime.toFixed(1)}秒`,
|
|
},
|
|
{ label: '魔法值', value: skillInfo.value?.attribute?.consumeMp },
|
|
{
|
|
label: '消耗无色小晶块',
|
|
value: skillInfo.value?.consumeItem?.value
|
|
? `${skillInfo.value?.consumeItem?.value}个`
|
|
: undefined,
|
|
},
|
|
],
|
|
)
|
|
|
|
const desc = computed(() => skillInfo.value?.descDetail.split('\n'))
|
|
|
|
const detail = computed(() => {
|
|
const items =
|
|
skillInfo.value?.attribute?.optionDesc?.split('\n').filter((item) => !!item) ?? []
|
|
const details = items?.map((a) => {
|
|
const beforeReplace = a.match(/^(.+?)\s*(\{value\d+\}.*)$/)
|
|
if (beforeReplace) {
|
|
a = `${beforeReplace[1]}<span class="skill_info_value">${beforeReplace[2]}</span>`
|
|
}
|
|
const matches = a.match(/{([^}]+)}/g)
|
|
if (matches) {
|
|
matches.forEach((match) => {
|
|
const key = match.replace(/[{}]/g, '')
|
|
// Only access if key matches the expected pattern
|
|
if (/^value.+/.test(key)) {
|
|
const value = skillInfo.value?.attribute?.optionValue[key as `value${string}`] ?? '-'
|
|
if (value) {
|
|
a = a.replace(match, `<span style="padding:0px 2px;color:#4AA256">${value}</span>`)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
return a
|
|
})
|
|
return details || []
|
|
})
|
|
|
|
const renderSkillDetail = () => (
|
|
<>
|
|
<UiDataSection
|
|
class="skill-detail__section"
|
|
title="基本信息"
|
|
compact
|
|
showState={false}
|
|
indicatorPosition="end"
|
|
>
|
|
<div class="skill-detail__stack">
|
|
{basic.value.map(
|
|
(item) =>
|
|
!!item.value && (
|
|
<div class="item skill-detail__row">
|
|
<span class="label">{item.label}</span>
|
|
<span class="value">{item.value}</span>
|
|
</div>
|
|
),
|
|
)}
|
|
</div>
|
|
</UiDataSection>
|
|
<UiDataSection
|
|
class="skill-detail__section"
|
|
title="技能描述"
|
|
compact
|
|
showState={false}
|
|
indicatorPosition="end"
|
|
>
|
|
<div class="skill-detail__description-frame">
|
|
<div class="skill-detail__scroll-content">
|
|
{desc.value?.map((item) => (
|
|
<div class="skill-detail__description-line">{item}</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</UiDataSection>
|
|
{detail.value.length > 0 && (
|
|
<UiDataSection
|
|
class="skill-detail__section skill-detail__section--grow"
|
|
title="技能属性"
|
|
compact
|
|
showState={false}
|
|
indicatorPosition="end"
|
|
>
|
|
<div class="skill-detail__flex-scroll">
|
|
<div class="skill-detail__stack">
|
|
{detail.value.map((item) => (
|
|
<div class="item skill-detail__row skill-detail__row--center" v-html={item}></div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</UiDataSection>
|
|
)}
|
|
</>
|
|
)
|
|
|
|
const renderSkillVp = () => (
|
|
<>
|
|
<div class="skill-detail__evolution">
|
|
<div class="skill-detail__evolution-list">
|
|
{skillInfo.value?.evolution?.map((item) => (
|
|
<>
|
|
<div class="skill-detail__stack">
|
|
<div class="skill_vp_title">{item.name}</div>
|
|
<UiDataSection
|
|
class="skill-detail__section"
|
|
title="技能描述"
|
|
compact
|
|
showState={false}
|
|
indicatorPosition="end"
|
|
>
|
|
<div class="skill-detail__evolution-scroll">
|
|
<div class="skill-detail__evolution-copy">{item.descDetail}</div>
|
|
</div>
|
|
</UiDataSection>
|
|
</div>
|
|
</>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</>
|
|
)
|
|
|
|
onMounted(() => {
|
|
watchEffect(() => {
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
;(skillInfo.value?.evolution?.length ?? 0) == 0 && (curTab.value = 0)
|
|
})
|
|
})
|
|
|
|
return () => (
|
|
<>
|
|
<div class="skill-detail">
|
|
<div class="skill_name">{skillInfo.value?.name}</div>
|
|
<div class="relative">
|
|
<TabsRoot v-model={curTab.value}>
|
|
<UiTabsList>
|
|
<UiTabsTrigger value={0}>技能信息</UiTabsTrigger>
|
|
<UiTabsTrigger value={1} disabled={!skillInfo.value?.evolution?.length}>
|
|
技能进化
|
|
</UiTabsTrigger>
|
|
</UiTabsList>
|
|
</TabsRoot>
|
|
</div>
|
|
{curTab.value === 0 && renderSkillDetail()}
|
|
{curTab.value === 1 && renderSkillVp()}
|
|
</div>
|
|
</>
|
|
)
|
|
},
|
|
})
|