dev
@@ -84,7 +84,7 @@ export interface ISkill {
|
||||
maxLv: number
|
||||
bind: boolean
|
||||
hasVP: boolean
|
||||
hasReinforce: boolean
|
||||
hasUP: boolean
|
||||
vps: {
|
||||
name: string
|
||||
desc: string
|
||||
|
||||
|
Before Width: | Height: | Size: 620 B After Width: | Height: | Size: 816 B |
@@ -0,0 +1,39 @@
|
||||
<svg width="22" height="20" viewBox="0 0 22 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g filter="url(#filter0_i_135_176)">
|
||||
<rect x="1" y="1" width="20" height="18" fill="url(#paint0_linear_135_176)"/>
|
||||
</g>
|
||||
<rect x="0.5" y="0.5" width="21" height="19" stroke="#49453F"/>
|
||||
<g filter="url(#filter1_d_135_176)">
|
||||
<path d="M11.1514 14.3975V12H6V11H16L11.1514 14.3975ZM10.8486 8.39746H16V9.39746H6L10.8486 6V8.39746Z" fill="url(#paint1_linear_135_176)"/>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_i_135_176" x="0" y="0" width="22" height="20" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset/>
|
||||
<feGaussianBlur stdDeviation="2"/>
|
||||
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
|
||||
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_135_176"/>
|
||||
</filter>
|
||||
<filter id="filter1_d_135_176" x="2" y="2" width="18" height="16.3975" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset/>
|
||||
<feGaussianBlur stdDeviation="2"/>
|
||||
<feComposite in2="hardAlpha" operator="out"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.44 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_135_176"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_135_176" result="shape"/>
|
||||
</filter>
|
||||
<linearGradient id="paint0_linear_135_176" x1="11" y1="1" x2="11" y2="19" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#0D3969"/>
|
||||
<stop offset="1" stop-color="#0A2244"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_135_176" x1="11" y1="6" x2="11" y2="14.3975" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#D6B17D"/>
|
||||
<stop offset="1" stop-color="#96763A"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 593 B After Width: | Height: | Size: 815 B |
@@ -0,0 +1,39 @@
|
||||
<svg width="22" height="18" viewBox="0 0 22 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g filter="url(#filter0_i_135_173)">
|
||||
<rect x="1" y="1" width="20" height="16" fill="url(#paint0_linear_135_173)"/>
|
||||
</g>
|
||||
<rect x="0.5" y="0.5" width="21" height="17" stroke="#49453F"/>
|
||||
<g filter="url(#filter1_d_135_173)">
|
||||
<path d="M11.1514 12.3975V10H6V9H16L11.1514 12.3975ZM10.8486 6.39746H16V7.39746H6L10.8486 4V6.39746Z" fill="url(#paint1_linear_135_173)"/>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_i_135_173" x="0" y="0" width="22" height="18" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset/>
|
||||
<feGaussianBlur stdDeviation="2"/>
|
||||
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
|
||||
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_135_173"/>
|
||||
</filter>
|
||||
<filter id="filter1_d_135_173" x="2" y="0" width="18" height="16.3975" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset/>
|
||||
<feGaussianBlur stdDeviation="2"/>
|
||||
<feComposite in2="hardAlpha" operator="out"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.44 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_135_173"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_135_173" result="shape"/>
|
||||
</filter>
|
||||
<linearGradient id="paint0_linear_135_173" x1="11" y1="1" x2="11" y2="17" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#306EB3"/>
|
||||
<stop offset="1" stop-color="#0A2244"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_135_173" x1="11" y1="4" x2="11" y2="12.3975" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#D6B17D"/>
|
||||
<stop offset="1" stop-color="#96763A"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 731 B |
@@ -0,0 +1,39 @@
|
||||
<svg width="22" height="20" viewBox="0 0 22 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g filter="url(#filter0_i_135_172)">
|
||||
<rect x="1" y="1" width="20" height="18" fill="url(#paint0_linear_135_172)"/>
|
||||
</g>
|
||||
<rect x="0.5" y="0.5" width="21" height="19" stroke="#49453F"/>
|
||||
<g filter="url(#filter1_d_135_172)">
|
||||
<path d="M11.1514 14.3975V12H6V11H16L11.1514 14.3975ZM10.8486 8.39746H16V9.39746H6L10.8486 6V8.39746Z" fill="url(#paint1_linear_135_172)"/>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_i_135_172" x="0" y="0" width="22" height="20" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset/>
|
||||
<feGaussianBlur stdDeviation="2"/>
|
||||
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
|
||||
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_135_172"/>
|
||||
</filter>
|
||||
<filter id="filter1_d_135_172" x="2" y="2" width="18" height="16.3975" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset/>
|
||||
<feGaussianBlur stdDeviation="2"/>
|
||||
<feComposite in2="hardAlpha" operator="out"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.44 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_135_172"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_135_172" result="shape"/>
|
||||
</filter>
|
||||
<linearGradient id="paint0_linear_135_172" x1="11" y1="1" x2="11" y2="19" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#626262"/>
|
||||
<stop offset="1"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_135_172" x1="11" y1="6" x2="11" y2="14.3975" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#D1D1D1"/>
|
||||
<stop offset="1" stop-color="#989898"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 645 B After Width: | Height: | Size: 905 B |
@@ -0,0 +1,39 @@
|
||||
<svg width="22" height="20" viewBox="0 0 22 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g filter="url(#filter0_i_135_174)">
|
||||
<rect x="1" y="1" width="20" height="18" fill="url(#paint0_linear_135_174)"/>
|
||||
</g>
|
||||
<rect x="0.5" y="0.5" width="21" height="19" stroke="#49453F"/>
|
||||
<g filter="url(#filter1_d_135_174)">
|
||||
<path d="M11.1514 14.3975V12H6V11H16L11.1514 14.3975ZM10.8486 8.39746H16V9.39746H6L10.8486 6V8.39746Z" fill="url(#paint1_linear_135_174)"/>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_i_135_174" x="0" y="0" width="22" height="20" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset/>
|
||||
<feGaussianBlur stdDeviation="2"/>
|
||||
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
|
||||
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_135_174"/>
|
||||
</filter>
|
||||
<filter id="filter1_d_135_174" x="2" y="2" width="18" height="16.3975" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset/>
|
||||
<feGaussianBlur stdDeviation="2"/>
|
||||
<feComposite in2="hardAlpha" operator="out"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.44 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_135_174"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_135_174" result="shape"/>
|
||||
</filter>
|
||||
<linearGradient id="paint0_linear_135_174" x1="11" y1="1" x2="11" y2="19" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#306EB3"/>
|
||||
<stop offset="1" stop-color="#0A2244"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_135_174" x1="11" y1="6" x2="11" y2="14.3975" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#D6B17D"/>
|
||||
<stop offset="1" stop-color="#96763A"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
@@ -1,178 +0,0 @@
|
||||
import { getImageURL, getLocalImageURL } from '@/utils/images'
|
||||
import type { ISkill } from '@/api/info/type'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
import CalcButton from '@/components/calc/button/index.vue'
|
||||
import CalcCheckbox from '@/components/calc/checkbox/index.vue'
|
||||
import CaclIconSelect from '@/components/calc/iconselect/index.vue'
|
||||
import CalcOption from '@/components/calc/option/index.vue'
|
||||
import { render, renderList } from 'vue'
|
||||
import './style.scss'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SkillTree',
|
||||
props: {
|
||||
skills: {
|
||||
type: Array as PropType<ISkill[]>,
|
||||
default: () => [],
|
||||
},
|
||||
lvInfo: {
|
||||
type: Object as PropType<Record<string, { lv: number; reinforce: number }>>,
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const lvInfo = useVModel(props, 'lvInfo')
|
||||
|
||||
const skills = (index: number = 0) => {
|
||||
index -= 1
|
||||
const reinforceList = Object.keys(lvInfo.value).filter(
|
||||
(a) => !!lvInfo.value[a].reinforce && lvInfo.value[a].reinforce > 0,
|
||||
)
|
||||
const currentReinforceSkill = index >= 0 ? reinforceList[index] : undefined
|
||||
return computed(() =>
|
||||
props.skills
|
||||
.filter(
|
||||
(a) =>
|
||||
a.id.toString() === currentReinforceSkill ||
|
||||
(a.hasReinforce &&
|
||||
(!lvInfo.value[a.id]?.reinforce || lvInfo.value[a.id]?.reinforce == 0) && lvInfo.value[a.id].lv > 0),
|
||||
)
|
||||
.sort((a, b) => a.learnLv - b.learnLv),
|
||||
)
|
||||
}
|
||||
|
||||
const itemChecked = (index: number, reinforce: number) => {
|
||||
index -= 1
|
||||
return computed<string | undefined>({
|
||||
get() {
|
||||
const reinforceList = Object.keys(lvInfo.value).filter(
|
||||
(a) => !!lvInfo.value[a].reinforce && lvInfo.value[a].reinforce > 0,
|
||||
)
|
||||
const currentReinforceSkill = reinforceList[index]
|
||||
const currentReinforce = lvInfo.value[currentReinforceSkill]?.reinforce
|
||||
console.log(currentReinforce, reinforce)
|
||||
return currentReinforce == reinforce ? currentReinforceSkill : undefined
|
||||
},
|
||||
set(value: string | undefined) {
|
||||
if (!value) return
|
||||
const reinforceList = Object.keys(lvInfo.value).filter(
|
||||
(a) => !!lvInfo.value[a].reinforce && lvInfo.value[a].reinforce > 0,
|
||||
)
|
||||
const currentReinforceSkill = reinforceList[index]
|
||||
currentReinforceSkill && (lvInfo.value[currentReinforceSkill].reinforce = 0)
|
||||
if (!value) {
|
||||
currentReinforceSkill && (lvInfo.value[currentReinforceSkill].reinforce = 0)
|
||||
} else {
|
||||
lvInfo.value[value].reinforce = reinforce
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const exchange = (index: number) => {
|
||||
const skill = itemChecked(index, 1).value || itemChecked(index, 2).value
|
||||
if (!skill) return
|
||||
lvInfo.value[skill].reinforce = lvInfo.value[skill].reinforce == 1 ? 2 : 1
|
||||
}
|
||||
|
||||
return () => (
|
||||
<>
|
||||
{lvInfo.value && Object.keys(lvInfo.value).length > 0 ? (
|
||||
<div class="flex pt-10px bg-black">
|
||||
<div class="skill-reinforce relative">
|
||||
<div class="absolute left-76px top-137px w-250px flex flex-col gap-21.5px">
|
||||
{renderList(3, (index) => (
|
||||
<>
|
||||
<div class="w-169px h-36px flex items-center justify-between">
|
||||
<div class="m-4px w-28px h-28px">
|
||||
<CaclIconSelect
|
||||
v-model:modelValue={itemChecked(index, 1).value}
|
||||
class="!bg-white/0 !border-white/0 m-4px"
|
||||
columnNum={4}
|
||||
>
|
||||
{renderList(skills(index).value, (item) => (
|
||||
<>
|
||||
<CalcOption value={item.id.toString()}>
|
||||
<img src={getImageURL(item.icon)} alt={item.name} />
|
||||
</CalcOption>
|
||||
</>
|
||||
))}
|
||||
</CaclIconSelect>
|
||||
</div>
|
||||
<CalcButton icon="exchange" onClick={() => exchange(index)}></CalcButton>
|
||||
<div class="m-4px w-28px h-28px">
|
||||
<CaclIconSelect
|
||||
v-model:modelValue={itemChecked(index, 2).value}
|
||||
class=" !bg-white/0 !border-white/0"
|
||||
columnNum={4}
|
||||
>
|
||||
{renderList(skills(index).value, (item) => (
|
||||
<>
|
||||
<CalcOption value={item.id.toString()}>
|
||||
<img src={getImageURL(item.icon)} alt={item.name} />
|
||||
</CalcOption>
|
||||
</>
|
||||
))}
|
||||
</CaclIconSelect>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
))}
|
||||
</div>
|
||||
<div class="absolute top-70px left-310px w-320px h-270px py-5px px-30px box-border flex flex-col">
|
||||
<div class="flex flex-wrap gap-10px content-start h-120px overflow-y-auto mb-10px">
|
||||
{renderList(skills().value, (item) => (
|
||||
<div
|
||||
key={item.id}
|
||||
class="w-[28px] h-[28px] rounded-[1px] border-[1px] border-solid border-[#6d4e2b] bg-[linear-gradient(180deg,_#191919_0%,_#000000_100%)] [box-shadow:0px_4px_4px_#00000040_inset] rounded-4px"
|
||||
>
|
||||
<img src={getImageURL(item.icon)} alt={item.name} />
|
||||
</div>
|
||||
))}
|
||||
{renderList(36 - skills().value.length, (item) => (
|
||||
<div
|
||||
key={item}
|
||||
class="w-[28px] h-[28px] rounded-[1px] border-[1px] border-solid border-[#6d4e2b] bg-[linear-gradient(180deg,_#191919_0%,_#000000_100%)] [box-shadow:0px_4px_4px_#00000040_inset] rounded-4px"
|
||||
></div>
|
||||
))}
|
||||
</div>
|
||||
<div class="flex flex-col gap-10px">
|
||||
{renderList(
|
||||
Object.keys(lvInfo.value).filter(
|
||||
(a) => !!lvInfo.value[a].reinforce && lvInfo.value[a].reinforce > 0,
|
||||
),
|
||||
(index) => {
|
||||
const skill = props.skills.find((a) => a.id.toString() === index)
|
||||
let tooltip = ''
|
||||
if (skill) {
|
||||
if (lvInfo.value[skill.id.toString()].reinforce == 1) {
|
||||
tooltip = `技能攻击力 +${skill.learnLv < 35 ? '60' : 55}%`
|
||||
}
|
||||
if (lvInfo.value[skill.id.toString()].reinforce == 2) {
|
||||
tooltip = `技能攻击力 +${skill.learnLv < 35 ? '43' : 38}%<br/>技能冷却时间 -15%`
|
||||
}
|
||||
}
|
||||
|
||||
return skill ? (
|
||||
<div class="flex gap-5px items-center">
|
||||
<div class="w-[28px] h-[28px] rounded-[1px] border-[1px] border-solid border-[#6d4e2b] bg-[linear-gradient(180deg,_#191919_0%,_#000000_100%)] [box-shadow:0px_4px_4px_#00000040_inset] rounded-4px">
|
||||
<img src={getImageURL(skill?.icon)} alt={skill.name} />
|
||||
</div>
|
||||
<div class="text-#947E4E" v-html={tooltip}></div>
|
||||
</div>
|
||||
) : (
|
||||
<></>
|
||||
)
|
||||
},
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
},
|
||||
})
|
||||
@@ -1,7 +0,0 @@
|
||||
.skill-reinforce {
|
||||
width: 620px;
|
||||
height: 334px;
|
||||
background-image: url('./img/bg.png');
|
||||
background-size: 100% 100%;
|
||||
background-color: black;
|
||||
}
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 724 B |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 77 KiB |
|
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 95 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
@@ -0,0 +1,285 @@
|
||||
import { getImageURL, getLocalImageURL } from '@/utils/images'
|
||||
import type { ISkill } from '@/api/info/type'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
import CalcButton from '@/components/calc/button/index.vue'
|
||||
import CalcCheckbox from '@/components/calc/checkbox/index.vue'
|
||||
import CaclIconSelect from '@/components/calc/iconselect/index.vue'
|
||||
import CalcOption from '@/components/calc/option/index.vue'
|
||||
import { render, renderList } from 'vue'
|
||||
import './style.scss'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SkillTree',
|
||||
props: {
|
||||
skills: {
|
||||
type: Array as PropType<ISkill[]>,
|
||||
default: () => [],
|
||||
},
|
||||
lvInfo: {
|
||||
type: Object as PropType<Record<string, { lv: number; up: number }>>,
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const lvInfo = useVModel(props, 'lvInfo')
|
||||
|
||||
const skills = (index: number = 0) => {
|
||||
index -= 1
|
||||
const upList = Object.keys(lvInfo.value).filter(
|
||||
(a) => !!lvInfo.value[a].up && lvInfo.value[a].up > 0,
|
||||
)
|
||||
const currentUPSkill = index >= 0 ? upList[index] : undefined
|
||||
return computed(() =>
|
||||
props.skills
|
||||
.filter(
|
||||
(a) =>
|
||||
a.id.toString() === currentUPSkill ||
|
||||
(a.hasUP &&
|
||||
(!lvInfo.value[a.id]?.up || lvInfo.value[a.id]?.up == 0) &&
|
||||
lvInfo.value[a.id].lv > 0),
|
||||
)
|
||||
.sort((a, b) => a.learnLv - b.learnLv),
|
||||
)
|
||||
}
|
||||
|
||||
const itemChecked = (index: number, up: number) => {
|
||||
index -= 1
|
||||
return computed<string | undefined>({
|
||||
get() {
|
||||
const upList = Object.keys(lvInfo.value).filter(
|
||||
(a) => !!lvInfo.value[a].up && lvInfo.value[a].up > 0,
|
||||
)
|
||||
const currentUPSkill = upList[index]
|
||||
const currentUP = lvInfo.value[currentUPSkill]?.up
|
||||
return currentUP == up ? currentUPSkill : undefined
|
||||
},
|
||||
set(value: string | undefined) {
|
||||
if (!value) return
|
||||
const upList = Object.keys(lvInfo.value).filter(
|
||||
(a) => !!lvInfo.value[a].up && lvInfo.value[a].up > 0,
|
||||
)
|
||||
const currentUPSkill = upList[index]
|
||||
currentUPSkill && (lvInfo.value[currentUPSkill].up = 0)
|
||||
if (!value) {
|
||||
currentUPSkill && (lvInfo.value[currentUPSkill].up = 0)
|
||||
} else {
|
||||
lvInfo.value[value].up = up
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const exchange = (index: number) => {
|
||||
const skill = itemChecked(index, 1).value || itemChecked(index, 2).value
|
||||
if (!skill) return
|
||||
lvInfo.value[skill].up = lvInfo.value[skill].up == 1 ? 2 : 1
|
||||
}
|
||||
|
||||
return () => (
|
||||
<>
|
||||
{lvInfo.value && Object.keys(lvInfo.value).length > 0 ? (
|
||||
<div class="flex bg-black">
|
||||
<div class="skill-up flex justify-between">
|
||||
<div class="left">
|
||||
<div class="w-full">
|
||||
<div class="flex justify-between">
|
||||
<div class="up_head_1">
|
||||
<div class="icon"></div>
|
||||
<div class="text-14px font-bold text-center">技能攻击力增加</div>
|
||||
</div>
|
||||
<div class="up_head_2">
|
||||
<div class="icon"></div>
|
||||
<div class="text-14px font-bold text-center">
|
||||
技能冷却时间减少
|
||||
<br />
|
||||
技能攻击力增加
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col gap-5px px-20px py-10px">
|
||||
{renderList(3, (index) => (
|
||||
<>
|
||||
<div class="flex items-center w-full justify-between">
|
||||
<div class={ `up_${!itemChecked(index, 1).value ? index : 'active'}`}>
|
||||
<CaclIconSelect
|
||||
v-model:modelValue={itemChecked(index, 1).value}
|
||||
class="!bg-white/0 !border-white/0"
|
||||
columnNum={4}
|
||||
>
|
||||
{renderList(skills(index).value, (item) => (
|
||||
<>
|
||||
<CalcOption value={item.id.toString()}>
|
||||
<img src={getImageURL(item.icon)} alt={item.name} />
|
||||
</CalcOption>
|
||||
</>
|
||||
))}
|
||||
</CaclIconSelect>
|
||||
</div>
|
||||
<CalcButton icon="exchange" onClick={() => exchange(index)}></CalcButton>
|
||||
<div class={ `up_${!itemChecked(index, 2).value ? index : 'active'}`}>
|
||||
<CaclIconSelect
|
||||
v-model:modelValue={itemChecked(index, 2).value}
|
||||
class=" !bg-white/0 !border-white/0"
|
||||
columnNum={4}
|
||||
>
|
||||
{renderList(skills(index).value, (item) => (
|
||||
<>
|
||||
<CalcOption value={item.id.toString()}>
|
||||
<img src={getImageURL(item.icon)} alt={item.name} />
|
||||
</CalcOption>
|
||||
</>
|
||||
))}
|
||||
</CaclIconSelect>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
))}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<div class="title text-16px text-center leading-48px">目标技能</div>
|
||||
<div class="flex flex-wrap gap-8px content-start h-110px overflow-y-auto mb-8px w-275px">
|
||||
{renderList(skills().value, (item) => (
|
||||
<div
|
||||
key={item.id}
|
||||
class="w-[28px] h-[28px] rounded-[1px] border-[1px] border-solid border-[#6d4e2b] bg-[linear-gradient(180deg,_#191919_0%,_#000000_100%)] [box-shadow:0px_4px_4px_#00000040_inset] rounded-4px"
|
||||
>
|
||||
<img src={getImageURL(item.icon)} alt={item.name} />
|
||||
</div>
|
||||
))}
|
||||
{renderList(35 - skills().value.length, (item) => (
|
||||
<div
|
||||
key={item}
|
||||
class="w-[28px] h-[28px] rounded-[1px] border-[1px] border-solid border-[#6d4e2b] bg-[linear-gradient(180deg,_#191919_0%,_#000000_100%)] [box-shadow:0px_4px_4px_#00000040_inset] rounded-4px"
|
||||
></div>
|
||||
))}
|
||||
</div>
|
||||
<div class="flex flex-col gap-10px">
|
||||
{renderList(
|
||||
Object.keys(lvInfo.value).filter(
|
||||
(a) => !!lvInfo.value[a].up && lvInfo.value[a].up > 0,
|
||||
),
|
||||
(index) => {
|
||||
const skill = props.skills.find((a) => a.id.toString() === index)
|
||||
let tooltip = ''
|
||||
if (skill) {
|
||||
if (lvInfo.value[skill.id.toString()].up == 1) {
|
||||
tooltip = `技能攻击力 +${skill.learnLv < 35 ? '60' : 55}%`
|
||||
}
|
||||
if (lvInfo.value[skill.id.toString()].up == 2) {
|
||||
tooltip = `技能冷却时间 -15%<br/>技能攻击力 +${skill.learnLv < 35 ? '43' : 38}%`
|
||||
}
|
||||
}
|
||||
|
||||
return skill ? (
|
||||
<div class="flex gap-10px items-center bg-[linear-gradient(180deg,_#1b1c1c_0%,_#000000_100%)] rounded-4px p-5px border-1px border-solid border-#2E2E2E">
|
||||
<div class="up_1 !w-38px !h-38px">
|
||||
<img src={getImageURL(skill?.icon)} alt={skill.name} />
|
||||
</div>
|
||||
<div class="text-#947E4E" v-html={tooltip}></div>
|
||||
</div>
|
||||
) : (
|
||||
<></>
|
||||
)
|
||||
},
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{/* <div class="absolute left-76px top-137px w-250px flex flex-col gap-21.5px">
|
||||
{renderList(3, (index) => (
|
||||
<>
|
||||
<div class="w-169px h-36px flex items-center justify-between">
|
||||
<div class="m-4px w-28px h-28px">
|
||||
<CaclIconSelect
|
||||
v-model:modelValue={itemChecked(index, 1).value}
|
||||
class="!bg-white/0 !border-white/0 m-4px"
|
||||
columnNum={4}
|
||||
>
|
||||
{renderList(skills(index).value, (item) => (
|
||||
<>
|
||||
<CalcOption value={item.id.toString()}>
|
||||
<img src={getImageURL(item.icon)} alt={item.name} />
|
||||
</CalcOption>
|
||||
</>
|
||||
))}
|
||||
</CaclIconSelect>
|
||||
</div>
|
||||
<CalcButton icon="exchange" onClick={() => exchange(index)}></CalcButton>
|
||||
<div class="m-4px w-28px h-28px">
|
||||
<CaclIconSelect
|
||||
v-model:modelValue={itemChecked(index, 2).value}
|
||||
class=" !bg-white/0 !border-white/0"
|
||||
columnNum={4}
|
||||
>
|
||||
{renderList(skills(index).value, (item) => (
|
||||
<>
|
||||
<CalcOption value={item.id.toString()}>
|
||||
<img src={getImageURL(item.icon)} alt={item.name} />
|
||||
</CalcOption>
|
||||
</>
|
||||
))}
|
||||
</CaclIconSelect>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
))}
|
||||
</div>
|
||||
<div class="absolute top-70px left-310px w-320px h-270px py-5px px-30px box-border flex flex-col">
|
||||
<div class="flex flex-wrap gap-10px content-start h-120px overflow-y-auto mb-10px">
|
||||
{renderList(skills().value, (item) => (
|
||||
<div
|
||||
key={item.id}
|
||||
class="w-[28px] h-[28px] rounded-[1px] border-[1px] border-solid border-[#6d4e2b] bg-[linear-gradient(180deg,_#191919_0%,_#000000_100%)] [box-shadow:0px_4px_4px_#00000040_inset] rounded-4px"
|
||||
>
|
||||
<img src={getImageURL(item.icon)} alt={item.name} />
|
||||
</div>
|
||||
))}
|
||||
{renderList(36 - skills().value.length, (item) => (
|
||||
<div
|
||||
key={item}
|
||||
class="w-[28px] h-[28px] rounded-[1px] border-[1px] border-solid border-[#6d4e2b] bg-[linear-gradient(180deg,_#191919_0%,_#000000_100%)] [box-shadow:0px_4px_4px_#00000040_inset] rounded-4px"
|
||||
></div>
|
||||
))}
|
||||
</div>
|
||||
<div class="flex flex-col gap-10px">
|
||||
{renderList(
|
||||
Object.keys(lvInfo.value).filter(
|
||||
(a) => !!lvInfo.value[a].up && lvInfo.value[a].up > 0,
|
||||
),
|
||||
(index) => {
|
||||
const skill = props.skills.find((a) => a.id.toString() === index)
|
||||
let tooltip = ''
|
||||
if (skill) {
|
||||
if (lvInfo.value[skill.id.toString()].up == 1) {
|
||||
tooltip = `技能攻击力 +${skill.learnLv < 35 ? '60' : 55}%`
|
||||
}
|
||||
if (lvInfo.value[skill.id.toString()].up == 2) {
|
||||
tooltip = `技能攻击力 +${skill.learnLv < 35 ? '43' : 38}%<br/>技能冷却时间 -15%`
|
||||
}
|
||||
}
|
||||
|
||||
return skill ? (
|
||||
<div class="flex gap-5px items-center">
|
||||
<div class="w-[28px] h-[28px] rounded-[1px] border-[1px] border-solid border-[#6d4e2b] bg-[linear-gradient(180deg,_#191919_0%,_#000000_100%)] [box-shadow:0px_4px_4px_#00000040_inset] rounded-4px">
|
||||
<img src={getImageURL(skill?.icon)} alt={skill.name} />
|
||||
</div>
|
||||
<div class="text-#947E4E" v-html={tooltip}></div>
|
||||
</div>
|
||||
) : (
|
||||
<></>
|
||||
)
|
||||
},
|
||||
)}
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,75 @@
|
||||
.skill-up {
|
||||
width: 550px;
|
||||
// height: 334px;
|
||||
// background-image: url('./img/bg.png');
|
||||
// background-size: 100% 100%;
|
||||
padding: 5px 10px;
|
||||
padding-bottom: 10px;
|
||||
background-color: black;
|
||||
|
||||
.left {
|
||||
width: 240px;
|
||||
height: 325px;
|
||||
border-radius: 2px;
|
||||
border: 1px solid #2E2E2E;
|
||||
background: linear-gradient(to bottom, #1c1c1c 0%, #0a0d0a 100%);
|
||||
display: flex;
|
||||
padding: 5px 10px;
|
||||
|
||||
.up_head_1,
|
||||
.up_head_2 {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
.icon {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
background-position: center center;
|
||||
}
|
||||
}
|
||||
|
||||
.up_head_1 .icon {
|
||||
background-image: url('./img/attack.png');
|
||||
}
|
||||
|
||||
.up_head_2 .icon {
|
||||
background-image: url('./img/cd.png');
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
.title {
|
||||
width: 271px;
|
||||
height: 48px;
|
||||
background: url('./img/title.png') no-repeat center center;
|
||||
}
|
||||
}
|
||||
|
||||
.up_1,
|
||||
.up_2,
|
||||
.up_3,
|
||||
.up_active {
|
||||
width: 54px;
|
||||
height: 54px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.up_1 {
|
||||
background: url('./img/up_1.png') no-repeat center center;
|
||||
}
|
||||
|
||||
.up_2 {
|
||||
background: url('./img/up_2.png') no-repeat center center;
|
||||
}
|
||||
|
||||
.up_3 {
|
||||
background: url('./img/up_3.png') no-repeat center center;
|
||||
}
|
||||
|
||||
.up_active {
|
||||
background: url('./img/up_active.png') no-repeat center center;
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 724 B |
@@ -57,7 +57,7 @@ export default defineComponent({
|
||||
{renderList(skills.value, (item) => (
|
||||
<div class="h-140px flex items-center vp pl-26px pr-16px box-content">
|
||||
<div class="w-30px text-center text-#816f4c">{item.learnLv}</div>
|
||||
<div class="w-200px flex gap-5px items-center">
|
||||
<div class="w-150px flex gap-5px items-center">
|
||||
<div class="border-1px border-solid border-#3F382E rounded-4px w-28px h-28px">
|
||||
<img class="w-28px h-28px" src={getImageURL(item.icon)} alt={item.name} />
|
||||
</div>
|
||||
@@ -66,7 +66,7 @@ export default defineComponent({
|
||||
{renderList(2, (index) => (
|
||||
<div
|
||||
class={[
|
||||
'flex items-center flex-col vp-item',
|
||||
'flex items-center flex-col vp-item py-10px',
|
||||
index == 1 ? 'ml-auto' : 'ml-2px',
|
||||
]}
|
||||
onClick={() => {
|
||||
@@ -75,8 +75,9 @@ export default defineComponent({
|
||||
index,
|
||||
).value
|
||||
}}
|
||||
>
|
||||
<div class="flex justify-between w-full h-30px px-5px">
|
||||
> <div class={["box-border w-full h-full pt-5px m-2px",itemChecked(item.id.toString(), index).value ? "selected": ""]} >
|
||||
<div class="flex justify-between w-full h-30px px-10px box-border">
|
||||
|
||||
<div class="flex items-start">
|
||||
<CalcCheckbox
|
||||
modelValue={itemChecked(item.id.toString(), index).value}
|
||||
@@ -96,13 +97,15 @@ export default defineComponent({
|
||||
src={getImageURL(item.icon)}
|
||||
alt={item.name}
|
||||
/>
|
||||
<div class={`vp_${index} absolute bottom--8px left-5px z-10`}></div>
|
||||
</div>
|
||||
<div class="w-16px"></div>
|
||||
</div>
|
||||
<div class="text-14px">{item.vps[index - 1]?.name}</div>
|
||||
<div class="text-13px mt-5px text-center">{item.vps[index - 1]?.name}</div>
|
||||
{renderList(item.vps[index - 1]?.desc.split('<br/>') ?? [], (desc) => (
|
||||
<div class="text-12px text-#816f4c flex items-center">{desc}</div>
|
||||
<div class="text-12px text-#816f4c text-center leading-none">{desc}</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -7,10 +7,37 @@
|
||||
}
|
||||
|
||||
.vp-item {
|
||||
height: 124px;
|
||||
width: 152px;
|
||||
height: 120px;
|
||||
width: 148px;
|
||||
padding:1px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-image: url(./img/bg.png);
|
||||
padding:5px 10px ;
|
||||
// padding:5px 10px ;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.selected {
|
||||
background-image: url(./img/selected.png);
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
background-size: calc(100% - 2.5px) calc(100% + 2.5px);
|
||||
}
|
||||
|
||||
.vp_1{
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url(../img/vp_1.png);
|
||||
}
|
||||
|
||||
.vp_2 {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url(../img/vp_2.png);
|
||||
}
|
||||
}
|
||||
|
||||
|
After Width: | Height: | Size: 1001 B |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 736 B |
|
After Width: | Height: | Size: 681 B |
@@ -14,7 +14,7 @@
|
||||
@click="tab = 1"
|
||||
:class="{ active: tab === 1 }"
|
||||
>
|
||||
技能VP
|
||||
技能定制
|
||||
</div>
|
||||
<!-- <div class="w-auto text-18px flex items-center justify-center !font-normal">|</div>
|
||||
<div
|
||||
@@ -30,7 +30,7 @@
|
||||
<calc-tab :value="1">技能VP</calc-tab>
|
||||
<calc-tab :value="2">技能突破</calc-tab>
|
||||
</calc-tabs> -->
|
||||
<div class="h-90vh w-620px overflow-x-hidden bg-#202020">
|
||||
<div class="h-90vh w-570px overflow-x-hidden bg-#101012">
|
||||
<div class="overflow-y-auto h-full" v-if="tab === 0">
|
||||
<SkillTree
|
||||
:skills="infoStore.skills"
|
||||
@@ -39,12 +39,14 @@
|
||||
></SkillTree>
|
||||
</div>
|
||||
<div v-if="tab === 1" class="flex flex-col overflow-y-hidden h-full">
|
||||
<SkillReinforce
|
||||
<div class="item-head">技能进化</div>
|
||||
<SkillUP
|
||||
class="flex-1"
|
||||
:skills="infoStore.skills"
|
||||
v-model:lvInfo="configStore.config.skills"
|
||||
v-model:bindAwake="configStore.config.bindAwake"
|
||||
></SkillReinforce>
|
||||
></SkillUP>
|
||||
<div class="item-head">技能突破</div>
|
||||
<div class="flex-1 overflow-y-auto w-full">
|
||||
<SkillVP
|
||||
:skills="infoStore.skills"
|
||||
@@ -61,7 +63,7 @@
|
||||
import { useInfoStore } from '@/stores/info'
|
||||
import SkillTree from './components/SkillTree'
|
||||
import SkillVP from './components/SkillVP'
|
||||
import SkillReinforce from './components/SkillReinforce'
|
||||
import SkillUP from './components/SkillUP'
|
||||
import { useConfigStore } from '@/stores'
|
||||
const props = defineProps<{
|
||||
alter: string
|
||||
@@ -97,4 +99,11 @@ const configStore = useConfigStore()
|
||||
transform: translate(0, 50%);
|
||||
}
|
||||
}
|
||||
|
||||
.item-head {
|
||||
background: linear-gradient(#2b2817, #171407);
|
||||
border-top: 1px solid #423d2c;
|
||||
border-bottom: 1px solid #211d15;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -32,7 +32,7 @@ export interface IConfigEquip {
|
||||
}
|
||||
|
||||
export interface IConfig {
|
||||
skills: Record<string, { lv: number ,vp:number, reinforce: number}>
|
||||
skills: Record<string, { lv: number ,vp:number, up: number}>
|
||||
equips: Record<string, IConfigEquip>
|
||||
jades: Record<
|
||||
string,
|
||||
@@ -161,7 +161,7 @@ export const useConfigStore = defineStore('configStore', () => {
|
||||
(config.value.skills[id] = {
|
||||
lv: infoStore.skills.find((skill) => skill.id.toString() === id)?.maxLearnLv ?? 0,
|
||||
vp: 0,
|
||||
reinforce: 0,
|
||||
up: 0,
|
||||
})
|
||||
})
|
||||
;(
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
$width: 20px,
|
||||
$height: 20px,
|
||||
$size: 100% 100%,
|
||||
$position: center center
|
||||
$position: center center,
|
||||
$img-type: 'png'
|
||||
) {
|
||||
background-image: url('@/assets/img/icon/#{$icon-name}.png') !important;
|
||||
background-image: url('@/assets/img/icon/#{$icon-name}.#{$img-type}') !important;
|
||||
background-repeat: no-repeat !important;
|
||||
background-size: $size !important;
|
||||
background-position: $position !important;
|
||||
@@ -13,13 +14,14 @@
|
||||
height: $height !important;
|
||||
|
||||
&:hover {
|
||||
background-image: url('@/assets/img/icon/#{$icon-name}_hover.png') !important;
|
||||
background-image: url('@/assets/img/icon/#{$icon-name}_hover.#{$img-type}') !important;
|
||||
}
|
||||
&:active {
|
||||
background-image: url('@/assets/img/icon/#{$icon-name}_active.png') !important;
|
||||
background-image: url('@/assets/img/icon/#{$icon-name}_active.#{$img-type}') !important;
|
||||
height: $height - 2px !important;
|
||||
}
|
||||
&:disabled {
|
||||
background-image: url('@/assets/img/icon/#{$icon-name}_disabled.png') !important;
|
||||
background-image: url('@/assets/img/icon/#{$icon-name}_disabled.#{$img-type}') !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,7 +114,7 @@
|
||||
}
|
||||
|
||||
.icon-exchange {
|
||||
@include icon-style('exchange', 20px, 20px, auto 100%);
|
||||
@include icon-style('exchange', 22px, 20px, auto 100%, center center, svg);
|
||||
}
|
||||
|
||||
|
||||
|
||||