new:新增技能代码导入

This commit is contained in:
2026-03-05 13:20:35 +08:00
parent f488b30577
commit 9a0a31ac2f
8 changed files with 137 additions and 35 deletions
-3
View File
@@ -1,3 +0,0 @@
from core.open.skillTree import get_skill_info
print(get_skill_info("eJytxzFOwmAAQOH3oA34U2gXQtDBMGBiSPBfSKBXIB5COjh1MDq4MXuDpju7CTsn8RaMLgbO4De85J2TNOm+87kF6e+/fj6+Ie5nVKbuHPLiDa1jcyf+UtB46ytSMSXzgRWP1ix8RkqWSmBDNBIdIImBNwL3BFJ7rNGCQAedoyP0Ds3QE3KkzxOaoGkjubRaY6bd9voljDaUNOa2HoDIippMqORid+3/O/8Bl00Yew=="))
+15 -1
View File
@@ -2,7 +2,7 @@ import re
from api.core.Auth import createToken from api.core.Auth import createToken
from api.core.Gzip import register_gzip_request from api.core.Gzip import register_gzip_request
import json import json
from fastapi import APIRouter,Request, Depends from fastapi import APIRouter,Request, Depends, Body
from typing import Annotated from typing import Annotated
from api.core.Response import Return, response from api.core.Response import Return, response
from api.core.Redis import get_redis_info from api.core.Redis import get_redis_info
@@ -10,6 +10,7 @@ from api.dp import RedisDep,AltersDep
from core.character.adventure import get_adv_list from core.character.adventure import get_adv_list
from core.basic.character import createCharacter from core.basic.character import createCharacter
from core.open.helper import get_user_info_by_id from core.open.helper import get_user_info_by_id
from core.open.skillTree import get_skill_tree_info
from api.core.exception import ResponseException from api.core.exception import ResponseException
router = APIRouter() router = APIRouter()
@@ -105,3 +106,16 @@ async def get_info_by_dnfhelper(uid: str, state: AltersDep, redis: RedisDep):
if isinstance(e, ResponseException): if isinstance(e, ResponseException):
return response(code=500, message=str(e), data=None) return response(code=500, message=str(e), data=None)
return response(code=500, message="Failed to fetch DNFHelper info", data=None) return response(code=500, message="Failed to fetch DNFHelper info", data=None)
@router.post("/skillTree/")
async def get_skill_by_code(state: AltersDep, code = Body(None)):
try:
skills = get_skill_tree_info(code.get("code", ""))
if skills.get("job",{}).get("class","") != state.alter:
return response(code=500, message="技能加点代码职业与登录职业不匹配", data=None)
return response(data=skills)
except Exception as e:
print(f"Error fetching skill tree info: {e}")
if isinstance(e, ResponseException):
return response(code=500, message=str(e), data=None)
return response(code=500, message="解析技能加点失败", data=None)
+11 -3
View File
@@ -403,7 +403,7 @@ def _parse_section2(sec2: bytes):
return evolutions, enhancements, keybinds, remaining return evolutions, enhancements, keybinds, remaining
def get_skill_info(encoded: str) -> dict: def get_skill_tree_info(encoded: str) -> dict:
r = decode_skill_hash(encoded) r = decode_skill_hash(encoded)
header = r['header'] header = r['header']
role = role_map.get(str(header['job_bytes'][0]), None) role = role_map.get(str(header['job_bytes'][0]), None)
@@ -443,10 +443,10 @@ def get_skill_info(encoded: str) -> dict:
chosen = next((x for x in candidates if x.type == ('active' if skill['skill_type'] == 1 else 'passive')), None) chosen = next((x for x in candidates if x.type == ('active' if skill['skill_type'] == 1 else 'passive')), None)
if chosen: if chosen:
skillLearn[str(chosen.id)] = { skillLearn[str(chosen.id)] = {
'level': skill['level'], 'lv': skill['level'],
'up': 0, 'up': 0,
'vp': 0, 'vp': 0,
'name': chosen.name, # 'name': chosen.name,
} }
# 处理进化 # 处理进化
@@ -460,6 +460,14 @@ def get_skill_info(encoded: str) -> dict:
for s in skillMap.get(enh['skill_index'], []): for s in skillMap.get(enh['skill_index'], []):
if getattr(s, 'hasUP', False) and str(s.id) in skillLearn: if getattr(s, 'hasUP', False) and str(s.id) in skillLearn:
skillLearn[str(s.id)]['up'] = enh['type'] skillLearn[str(s.id)]['up'] = enh['type']
for i in character.skills:
if (i.learnLv in [50,85] or i.name == '基础精通') and str(i.id) not in skillLearn:
skillLearn[str(i.id)] = {
'lv': i.calculate_lv(),
'up': 0,
'vp': 0,
# 'name': i.name,
}
return { return {
"name": header['name'], "name": header['name'],
"level": header['level'], "level": header['level'],
+23 -1
View File
@@ -8,6 +8,10 @@ import skipFormatting from '@vue/eslint-config-prettier/skip-formatting'
// configureVueProject({ scriptLangs: ['ts', 'tsx'] }) // configureVueProject({ scriptLangs: ['ts', 'tsx'] })
// More info at https://github.com/vuejs/eslint-config-typescript/#advanced-setup // More info at https://github.com/vuejs/eslint-config-typescript/#advanced-setup
// To allow more languages other than `ts` in `.vue` files, uncomment the following lines:
import { configureVueProject } from '@vue/eslint-config-typescript'
configureVueProject({ scriptLangs: ['ts', 'tsx'] })
export default defineConfigWithVueTs( export default defineConfigWithVueTs(
{ {
name: 'app/files-to-lint', name: 'app/files-to-lint',
@@ -21,5 +25,23 @@ export default defineConfigWithVueTs(
pluginVue.configs['flat/essential'], pluginVue.configs['flat/essential'],
vueTsConfigs.recommended, vueTsConfigs.recommended,
...oxlint.configs['flat/recommended'], ...oxlint.configs['flat/recommended'],
skipFormatting, {
rules: {
'vue/multi-word-component-names': 'off',
},
},
// skipFormatting,
{
files: ['**/*.vue'],
languageOptions: {
parserOptions: {
parser: '@typescript-eslint/parser', // 内部使用 TypeScript 解析器
ecmaVersion: 'latest',
sourceType: 'module',
ecmaFeatures: {
jsx: true,
},
},
},
},
) )
+4
View File
@@ -22,6 +22,10 @@ export default defineRequest((request) => {
async getConfigFromHelper(uid: string) { async getConfigFromHelper(uid: string) {
const res = await request.get(`/dnfhelper/${uid}/`) const res = await request.get(`/dnfhelper/${uid}/`)
return res.data return res.data
},
async getSkillFromCode(code: string) {
const res = await request.post(`/skillTree/`, { code })
return res.data
} }
} }
}) })
+1 -25
View File
@@ -1,6 +1,6 @@
<script lang="tsx"> <script lang="tsx">
import { useAsyncState } from '@vueuse/core' import { useAsyncState } from '@vueuse/core'
import { computed, defineComponent, ref, renderList } from 'vue' import { defineComponent, ref } from 'vue'
import api from '@/api' import api from '@/api'
import { useDialog } from '@/components/hooks/dialog' import { useDialog } from '@/components/hooks/dialog'
import { isShow, onShow } from '@/components/hooks/show' import { isShow, onShow } from '@/components/hooks/show'
@@ -42,30 +42,6 @@ export default defineComponent({
const visible = isShow() const visible = isShow()
const configList = computed(() => {
return Object.keys(state.value ?? {}).sort()
})
async function importConfigs() {
// if (window.pywebview) {
// const configs = {}
// cacheList.value.forEach(key => {
// configs[key] = state.value?.[key]
// })
// await api.importConfigs(configs)
// } else {
// cacheList.value.forEach(key => {
// localStorage.setItem(key, JSON.stringify(state.value?.[key]))
// })
// }
// const { alert } = useDialog()
// await alert({
// content: "导入成功"
// })
// visible.value = false
// await configStore.load()
}
return () => { return () => {
return ( return (
<> <>
@@ -0,0 +1,70 @@
<script lang="tsx">
import { useAsyncState } from '@vueuse/core'
import { defineComponent, ref } from 'vue'
import api from '@/api'
import { useDialog } from '@/components/hooks/dialog'
import { isShow, onShow } from '@/components/hooks/show'
import { useConfigStore } from '@/stores'
export default defineComponent({
setup() {
const configStore = useConfigStore()
const skillCode = ref('')
const { state, execute, isLoading } = useAsyncState(
async () => {
const res = await api.getSkillFromCode(skillCode.value)
console.log(res)
configStore.config.skills = res.skills
const { alert } = useDialog()
visible.value = false
await alert({
content: '导入成功',
})
return res
},
undefined,
{
resetOnExecute: false,
immediate: false,
onError: Promise.reject,
},
)
onShow(
() => {
skillCode.value = ''
state.value = undefined
},
{ immediate: true },
)
const visible = isShow()
return () => {
return (
<>
<div class="h-35 w-80 py-2 px-4 text-hex-e9c556">
<div class="flex justify-around items-center">
技能加点代码
<calc-input class="!w-60" v-model={skillCode.value} />
</div>
<div>
<p class="text-hex-e9c556/80">
* 点击导入后会根据规则解析出技能加点、技能进化、技能强化
</p>
<p class="text-hex-e9c556/80">
* 部分技能可能存在无法识别的情况,需要手动调整
</p>
</div>
<div class="flex justify-around items-center">
<calc-button onClick={execute} disabled={!skillCode.value || isLoading.value}>导入</calc-button>
<calc-button onClick={() => (visible.value = false)}>取消</calc-button>
</div>
</div>
</>
)
}
},
})
</script>
+12 -1
View File
@@ -22,18 +22,25 @@
<calc-checkbox round v-model="configStore.config.DSB">系统奶</calc-checkbox> <calc-checkbox round v-model="configStore.config.DSB">系统奶</calc-checkbox>
<calc-checkbox round v-model="configStore.config.BUFF">组队</calc-checkbox> <calc-checkbox round v-model="configStore.config.BUFF">组队</calc-checkbox>
<calc-button title="打造导入" @click="showImport" class="ml-1" icon="import"></calc-button> <calc-button title="打造导入" @click="showImport" class="ml-1" icon="import"></calc-button>
<calc-button title="技能导入" @click="showImportSkill" class="ml-1" icon="exchange"></calc-button>
</div> </div>
</div> </div>
<calc-dialog lazy header="存档导入" v-model:visible="importVisible"> <calc-dialog lazy header="打造导入" v-model:visible="importVisible">
<ImportVue></ImportVue> <ImportVue></ImportVue>
</calc-dialog> </calc-dialog>
<calc-dialog lazy header="技能导入" v-model:visible="importSkillVisible">
<ImportSkillVue></ImportSkillVue>
</calc-dialog>
</template> </template>
<script lang="ts" setup name="Index"> <script lang="ts" setup name="Index">
import { useInfoStore } from '@/stores/info' import { useInfoStore } from '@/stores/info'
import { useConfigStore } from '@/stores' import { useConfigStore } from '@/stores'
import ImportVue from './Config/import.vue'; import ImportVue from './Config/import.vue';
import ImportSkillVue from './Config/importSkill.vue';
import Result from './Result/Index.vue' import Result from './Result/Index.vue'
const props = defineProps<{ const props = defineProps<{
alter: string alter: string
@@ -41,6 +48,7 @@ const props = defineProps<{
const infoStore = useInfoStore() const infoStore = useInfoStore()
const configStore = useConfigStore() const configStore = useConfigStore()
const importVisible = ref(false) const importVisible = ref(false)
const importSkillVisible = ref(false)
const stopWatch = watch( const stopWatch = watch(
() => { () => {
@@ -55,6 +63,9 @@ const showImport = () => {
importVisible.value = true importVisible.value = true
} }
const showImportSkill = () => {
importSkillVisible.value = true
}
onMounted(async () => { onMounted(async () => {
await infoStore.createCharacter(props.alter, '0') await infoStore.createCharacter(props.alter, '0')
window.addEventListener('beforeunload', () => { window.addEventListener('beforeunload', () => {