添加列表及一键导入

This commit is contained in:
2026-05-28 18:02:34 +08:00
parent 1fc3326f2e
commit 3a590e1c60
10 changed files with 173 additions and 20 deletions
+18 -3
View File
@@ -11,7 +11,7 @@ from api.dp import RedisDep, AltersDep
from core.basic.equipment import get_equipment from core.basic.equipment import get_equipment
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, get_user_list_by_id from core.open.helper import get_user_info_by_id, get_user_info_by_role_id, get_user_list_by_id, getRoleJobCode
from core.open.skillTree import get_skill_tree_info from core.open.skillTree import get_skill_tree_info
from api.core.exception import ResponseException from api.core.exception import ResponseException
@@ -34,9 +34,12 @@ def replace_placeholders(template):
@router.get('/adventure') @router.get('/adventure')
async def get_adventure_info(request: Request, redis: RedisDep): async def get_adventure_info(request: Request, redis: RedisDep, name: str = None):
adventure_info = get_redis_info(redis, 'dcalc:adventure', get_adv_list) adventure_info = get_redis_info(redis, 'dcalc:adventure', get_adv_list)
if name:
total = [item for job in adventure_info for item in job.get('children', [])]
code = getRoleJobCode(name)
adventure_info = next((x for x in total if (x['title'] == name or x['name'] == code) and x['open']), None)
return response(data=adventure_info) return response(data=adventure_info)
@@ -128,6 +131,18 @@ async def get_dnfhelper_list(uid: str, redis: RedisDep):
# return response(code=500, message='Failed to fetch DNFHelper list', data=None) # return response(code=500, message='Failed to fetch DNFHelper list', data=None)
@router.get('/dnfhelper/{uid}/{id}/')
async def get_dnfhelper_detail(uid: str, id: str, state: AltersDep, redis: RedisDep):
cache_key = f'dnfhelper:{uid}:{id}'
async def get_detail():
return await get_user_info_by_role_id(uid, id, state)
result = await get_redis_info_async(redis, cache_key, get_detail, expire=12 * 60 * 60)
return response(data=result)
# return response(code=500, message='Failed to fetch DNFHelper detail', data=None)
@router.get('/dnfhelper/{uid}/') @router.get('/dnfhelper/{uid}/')
async def get_info_by_dnfhelper(uid: str, state: AltersDep, redis: RedisDep): async def get_info_by_dnfhelper(uid: str, state: AltersDep, redis: RedisDep):
try: try:
+13
View File
@@ -86,6 +86,19 @@ async def get_user_list_by_id(user_id: str):
return helper_list return helper_list
def getRoleJobCode(jobName: str):
return job_mapping.get(jobName, None)
async def get_user_info_by_role_id(user_id: str, role_id: str, alter: AltersDep):
# 通过OCR助手获取用户信息
helper_info = await get_main_user_info_by_id(user_id, None, role_id)
if helper_info is None:
raise ResponseException('当前助手ID不存在或已隐藏,请确认后重试')
else:
return trans_to_dcalc_set(helper_info, alter)
async def get_user_info_by_id(user_id: str, alter: AltersDep): async def get_user_info_by_id(user_id: str, alter: AltersDep):
if alter is None: if alter is None:
raise ResponseException('登录过期或无效Token,请刷新后重试') raise ResponseException('登录过期或无效Token,请刷新后重试')
+9 -1
View File
@@ -1,5 +1,5 @@
import { defineRequest } from '../common' import { defineRequest } from '../common'
import type { IAdventureInfo, ICharacterInfo, IHelperInfo, ISkillInfo } from './type' import type { IAdventureInfo, IAlterInfo, ICharacterInfo, IHelperInfo, ISkillInfo } from './type'
export default defineRequest((request) => { export default defineRequest((request) => {
return { return {
@@ -7,6 +7,10 @@ export default defineRequest((request) => {
const res = await request.get<IAdventureInfo[]>('/adventure') const res = await request.get<IAdventureInfo[]>('/adventure')
return res.data return res.data
}, },
async alterByName(name: string) {
const res = await request.get<IAlterInfo>('/adventure', { params: { name } })
return res.data
},
async createToken(alter: string, equVersion?: string) { async createToken(alter: string, equVersion?: string) {
const res = await request.get<string>(`/token/get/${alter}`, { params: { equVersion } }) const res = await request.get<string>(`/token/get/${alter}`, { params: { equVersion } })
return res.data return res.data
@@ -23,6 +27,10 @@ export default defineRequest((request) => {
const res = await request.get(`/dnfhelper/${uid}/`) const res = await request.get(`/dnfhelper/${uid}/`)
return res.data return res.data
}, },
async getConfigFromHelperAlter(uid: string, alter: string) {
const res = await request.get(`/dnfhelper/${uid}/${alter}`)
return res.data
},
async getSkillFromCode(code: string) { async getSkillFromCode(code: string) {
const res = await request.post(`/skillTree/`, { code }) const res = await request.post(`/skillTree/`, { code })
return res.data return res.data
+9 -7
View File
@@ -216,15 +216,17 @@ export interface Attribute {
detail: string detail: string
} }
export interface IHelperRoleInfo {
roleId: string
roleName: string
roleJob: string
avatarLink: string
fame: number
}
export interface IHelperInfo { export interface IHelperInfo {
id: string id: string
avatar: string avatar: string
name: string name: string
roleList: { roleList: IHelperRoleInfo[]
roleId: string
roleName: string
roleJob: string
avatarLink: string
fame: number
}[]
} }
@@ -0,0 +1,80 @@
<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'
import { type IHelperRoleInfo } from '@/api/info/type'
export default defineComponent({
props: {
alter: {
type: Object as () => IHelperRoleInfo,
},
uid: {
type: String,
},
},
setup(props) {
const configStore = useConfigStore()
const { state, execute, isLoading } = useAsyncState(
async () => {
const res = await api.getConfigFromHelperAlter(props.uid || '', props.alter?.roleId || '')
configStore.config.equips = res.equips
configStore.config.avatar = res.avatars
configStore.config.avatarLink = res.avatarLink
configStore.config.emblems = res.emblems
configStore.config.sundry.fog = res.fogOathLv
configStore.config.oaths = res.oaths
const { alert } = useDialog()
visible.value = false
await alert({
content: '导入成功',
})
return res
},
undefined,
{
resetOnExecute: false,
immediate: false,
onError: Promise.reject,
},
)
onShow(
() => {
state.value = undefined
},
{ immediate: true },
)
const visible = isShow()
return () => {
return (
<>
<div class="h-45 w-80 py-2 px-4 text-#e9c556">
<div class="flex justify-around items-center flex-col gap-1">
<div>检测到以下信息,是否导入助手数据?</div>
<div class="text-#DED29A">{props.alter?.roleName}</div>
<div class="text-#908150">{props.alter?.roleJob}</div>
<div class="text-#3ea74e">名望:{props.alter?.fame}</div>
</div>
<div>
<p class="text-#e9c556/80">* 点击导入后会从助手通过文字识别获取打造</p>
<p class="text-#e9c556/80">* 部分打造无法获取,此处仅做快捷导入</p>
</div>
<div class="flex justify-around items-center">
<calc-button onClick={execute} disabled={isLoading.value}>
导入
</calc-button>
<calc-button onClick={() => (visible.value = false)}>取消</calc-button>
</div>
</div>
</>
)
}
},
})
</script>
+23 -2
View File
@@ -1,7 +1,7 @@
<template> <template>
<div class="w-100% h-100% main flex" :class="infoStore.infos?.alter"> <div class="w-100% h-100% main flex" :class="infoStore.infos?.alter">
<div class="header"> <div class="header">
<calc-tabs route> <calc-tabs route :query="route.query">
<calc-tab :value="`/character/equipment/${props.alter}`">装备设置</calc-tab> <calc-tab :value="`/character/equipment/${props.alter}`">装备设置</calc-tab>
<calc-tab :value="`/character/skill/${props.alter}`">技能设置</calc-tab> <calc-tab :value="`/character/skill/${props.alter}`">技能设置</calc-tab>
<calc-tab :value="`/character/forge/${props.alter}`">打造设置</calc-tab> <calc-tab :value="`/character/forge/${props.alter}`">打造设置</calc-tab>
@@ -38,6 +38,10 @@
<calc-dialog lazy header="技能导入" v-model:visible="importSkillVisible"> <calc-dialog lazy header="技能导入" v-model:visible="importSkillVisible">
<ImportSkillVue></ImportSkillVue> <ImportSkillVue></ImportSkillVue>
</calc-dialog> </calc-dialog>
<calc-dialog lazy header="助手打造导入" v-model:visible="helperImport">
<ImportDnfhelper :alter="toImport" :uid="helperStore.helperInfo?.id"></ImportDnfhelper>
</calc-dialog>
</template> </template>
<script lang="ts" setup name="Index"> <script lang="ts" setup name="Index">
@@ -45,16 +49,22 @@ 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 ImportSkillVue from './Config/importSkill.vue'
import ImportDnfhelper from './Config/importDnfhelper.vue'
import Result from './Result/Index.vue' import Result from './Result/Index.vue'
import { useDnfHelperStore } from '@/stores/dnfhelper.ts'
import { type IHelperRoleInfo } from '@/api/info/type'
const props = defineProps<{ const props = defineProps<{
alter: string alter: string
}>() }>()
const infoStore = useInfoStore() const infoStore = useInfoStore()
const configStore = useConfigStore() const configStore = useConfigStore()
const helperImport = ref(false)
const importVisible = ref(false) const importVisible = ref(false)
const importSkillVisible = ref(false) const importSkillVisible = ref(false)
const helperStore = useDnfHelperStore()
const toImport = ref<IHelperRoleInfo>()
const shouldWatch = ref(true) // const shouldWatch = ref(true)
const isExecuting = ref(false) const isExecuting = ref(false)
@@ -81,11 +91,22 @@ const showImport = () => {
const showImportSkill = () => { const showImportSkill = () => {
importSkillVisible.value = true importSkillVisible.value = true
} }
const route = useRoute()
onMounted(async () => { onMounted(async () => {
await infoStore.createCharacter(props.alter, '0') await infoStore.createCharacter(props.alter, '0')
window.addEventListener('beforeunload', () => { window.addEventListener('beforeunload', () => {
configStore.saveConfig() configStore.saveConfig()
}) })
// 检测router的传参
const { roleId } = route.query
if (roleId) {
toImport.value = helperStore.helperInfo?.roleList.find((a) => a.roleId === roleId)
if (toImport.value) {
helperImport.value = true
}
}
}) })
onUnmounted(() => { onUnmounted(() => {
+17 -3
View File
@@ -39,6 +39,8 @@
</div> </div>
</template> </template>
<script setup lang="ts" name="dnfhelper-list"> <script setup lang="ts" name="dnfhelper-list">
import api from '@/api'
import { useDialog } from '@/components/hooks/dialog'
import router from '@/router' import router from '@/router'
import { useDnfHelperStore } from '@/stores/dnfhelper' import { useDnfHelperStore } from '@/stores/dnfhelper'
import { computed } from 'vue' import { computed } from 'vue'
@@ -70,12 +72,24 @@ const navToHome = () => {
} }
const chooseRole = ({ roleId }: { roleId: string }) => { const chooseRole = ({ roleId }: { roleId: string }) => {
console.log(roleId)
acitveRoleId.value = roleId acitveRoleId.value = roleId
} }
const importRole = () => { const { alert } = useDialog()
console.log('import')
const currentRoleInfo = computed(() => {
return list.value.find((item) => item.roleId === acitveRoleId.value)
})
const importRole = async () => {
if (!acitveRoleId.value) return if (!acitveRoleId.value) return
const alter = await api.alterByName(currentRoleInfo.value?.roleJob || '')
if (!alter) {
return await alert({
content: '当前职业尚在开发中,敬请期待。',
})
} else {
return window.open(`/character/equipment/${alter.value}?roleId=${acitveRoleId.value}`, '_blank')
}
} }
</script> </script>
+1 -1
View File
@@ -17,7 +17,7 @@ const routes: RouteRecordRaw[] = [
{ {
path: '/character/:alter', path: '/character/:alter',
redirect: (to) => { redirect: (to) => {
return { path: `/character/equipment/${to.params.alter}` } return { path: `/character/equipment/${to.params.alter}`, query: to.query }
}, },
props: true, props: true,
name: 'character', name: 'character',
+2 -2
View File
@@ -49,12 +49,12 @@ export default defineConfig({
proxy: { proxy: {
'/api': { '/api': {
target: 'http://127.0.0.1:47173/api', target: 'http://127.0.0.1:47173/api',
changeOrigin: true, changeOrigin: false,
rewrite: (path) => path.replace(/^\/api/, ''), rewrite: (path) => path.replace(/^\/api/, ''),
}, },
'/image': { '/image': {
target: 'http://127.0.0.1:3000', target: 'http://127.0.0.1:3000',
changeOrigin: true, changeOrigin: false,
rewrite: (path) => path.replace(/^\/image/, ''), rewrite: (path) => path.replace(/^\/image/, ''),
}, },
}, },