dev
This commit is contained in:
@@ -34,7 +34,7 @@ def dict2obj(dictObj):
|
|||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
||||||
async def createToken(alter: str, equVersion: str, expire=86400 / 24 * 2, redis=None, env=''):
|
def createToken(alter: str, equVersion: str, redis = None, expire=86400 / 24 * 2)->str:
|
||||||
ts_str = str(time.time() + expire)
|
ts_str = str(time.time() + expire)
|
||||||
ts_byte = ts_str.encode('utf-8')
|
ts_byte = ts_str.encode('utf-8')
|
||||||
sha1_tshex_str = hmac.new(alter.encode('utf-8'), ts_byte, 'sha1').hexdigest()
|
sha1_tshex_str = hmac.new(alter.encode('utf-8'), ts_byte, 'sha1').hexdigest()
|
||||||
@@ -42,15 +42,16 @@ async def createToken(alter: str, equVersion: str, expire=86400 / 24 * 2, redis=
|
|||||||
token = base64.urlsafe_b64encode(token.encode('utf-8')).decode('utf-8')
|
token = base64.urlsafe_b64encode(token.encode('utf-8')).decode('utf-8')
|
||||||
# character = createCharacter(alter)
|
# character = createCharacter(alter)
|
||||||
character = {}
|
character = {}
|
||||||
await redis.set(f'token:{token}', json.dumps(AlterState(alter, token, character, equVersion).to_dict()), int(expire))
|
redis.set(f'token:{token}', json.dumps(AlterState(alter, token, character, equVersion).to_dict()), int(expire))
|
||||||
return token
|
return token
|
||||||
|
|
||||||
|
|
||||||
async def readToken(token: str, redis, env) -> AlterState:
|
def readToken(token: str, redis) -> AlterState:
|
||||||
info = None
|
info = None
|
||||||
try:
|
try:
|
||||||
info = dict2obj(json.loads(await redis.get(f'token:{token}')))
|
info = dict2obj(json.loads(redis.get(f'token:{token}')))
|
||||||
except Exception:
|
except Exception as ex:
|
||||||
|
print(ex)
|
||||||
ResponseException('登录过期或无效Token,请刷新后重试')
|
ResponseException('登录过期或无效Token,请刷新后重试')
|
||||||
if info is None:
|
if info is None:
|
||||||
raise ResponseException('登录过期或无效Token,请刷新后重试')
|
raise ResponseException('登录过期或无效Token,请刷新后重试')
|
||||||
@@ -62,20 +63,7 @@ def deleteToken(token, redis, env):
|
|||||||
return token
|
return token
|
||||||
|
|
||||||
|
|
||||||
async def authorize(request: Request, access_token: Optional[str] = Header(None)):
|
def uid(access_uid: Optional[str] = Header(None)):
|
||||||
if access_token is not None:
|
|
||||||
info = await readToken(access_token, request.app.state.redis, request.app.state.env)
|
|
||||||
return info
|
|
||||||
else:
|
|
||||||
raise ResponseException('登录过期或无效Token,请刷新后重试')
|
|
||||||
|
|
||||||
|
|
||||||
def unauthorize(request: Request, access_token: Optional[str] = Header(None)):
|
|
||||||
if access_token is not None:
|
|
||||||
return deleteToken(access_token, request.app.state.redis, request.app.state.env)
|
|
||||||
|
|
||||||
|
|
||||||
async def uid(request: Request, access_uid: Optional[str] = Header(None)):
|
|
||||||
try:
|
try:
|
||||||
return int(access_uid)
|
return int(access_uid)
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|||||||
+19
-2
@@ -1,9 +1,26 @@
|
|||||||
from typing import Annotated
|
from typing import Annotated, Optional
|
||||||
from redis import Redis
|
from redis import Redis
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
from fastapi import Depends
|
from fastapi import Depends, Header
|
||||||
|
|
||||||
|
from api.core.exception import ResponseException
|
||||||
from database.connect import get_db,get_redis
|
from database.connect import get_db,get_redis
|
||||||
|
from api.core.Auth import AlterState, deleteToken, readToken
|
||||||
|
|
||||||
SessionDep = Annotated[Session, Depends(get_db)]
|
SessionDep = Annotated[Session, Depends(get_db)]
|
||||||
RedisDep = Annotated[Redis, Depends(get_redis)]
|
RedisDep = Annotated[Redis, Depends(get_redis)]
|
||||||
|
|
||||||
|
|
||||||
|
def authorize(redis:RedisDep, access_token: Optional[str] = Header(None)):
|
||||||
|
if access_token is not None:
|
||||||
|
info = readToken(access_token, redis)
|
||||||
|
return info
|
||||||
|
else:
|
||||||
|
raise ResponseException('登录过期或无效Token,请刷新后重试')
|
||||||
|
|
||||||
|
|
||||||
|
def unauthorize(redis:RedisDep, access_token: Optional[str] = Header(None)):
|
||||||
|
if access_token is not None:
|
||||||
|
return deleteToken(access_token, redis)
|
||||||
|
|
||||||
|
AltersDep = Annotated[AlterState, Depends(authorize)]
|
||||||
+17
-18
@@ -4,7 +4,8 @@ import json
|
|||||||
from fastapi import APIRouter,Request
|
from fastapi import APIRouter,Request
|
||||||
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
|
||||||
from api.dp import RedisDep
|
from api.dp import RedisDep,AltersDep
|
||||||
|
from core.basic.character import createCharacter
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
@@ -20,22 +21,20 @@ async def get_adventure_info(request: Request,redis:RedisDep):
|
|||||||
|
|
||||||
return response(data=adventure_info)
|
return response(data=adventure_info)
|
||||||
|
|
||||||
@router.get('/equipment/list')
|
@router.get("/token/get/{alter}")
|
||||||
async def get_equipment_list(request: Request,redis:RedisDep):
|
async def getToken(redis:RedisDep,
|
||||||
def get_equipment_list():
|
alter: str, request: Request, version: str = None, equVersion: str = "0"
|
||||||
with open('./dataFiles/equipment-list.json', encoding='utf-8') as fp:
|
|
||||||
return json.load(fp)
|
|
||||||
equipment_list = get_redis_info(redis, 'dcalc:equipment', get_equipment_list)
|
|
||||||
|
|
||||||
return response(data=equipment_list)
|
|
||||||
|
|
||||||
@router.get("/token/get/{alter}", response_model=Return[str])
|
|
||||||
async def getToken(
|
|
||||||
alter: str, request: Request, version: str = None, equVersion: str = ""
|
|
||||||
):
|
):
|
||||||
if version is not None and version != "default" and version != "":
|
token = createToken(alter, equVersion, redis)
|
||||||
alter = version + "." + alter
|
|
||||||
token = createToken(
|
|
||||||
alter, equVersion, redis=request.app.state.redis, env=request.app.state.env
|
|
||||||
)
|
|
||||||
return response(data=token)
|
return response(data=token)
|
||||||
|
|
||||||
|
@router.get("/character")
|
||||||
|
async def get_character_info(
|
||||||
|
request: Request, state: AltersDep ,redis:RedisDep
|
||||||
|
):
|
||||||
|
character = createCharacter(state.alter, state.equVersion)
|
||||||
|
def get_character():
|
||||||
|
return character.getInfo()
|
||||||
|
info = get_redis_info(redis, f"dcalc:character:{state.alter}", get_character)
|
||||||
|
return response(data=info)
|
||||||
|
|
||||||
|
|||||||
@@ -569,7 +569,9 @@ class Character:
|
|||||||
|
|
||||||
def createCharacter(alter: str, equVersion: str = '0'):
|
def createCharacter(alter: str, equVersion: str = '0'):
|
||||||
character: Character = None
|
character: Character = None
|
||||||
module_name = 'core.characters.' + alter
|
module_name = 'core.character.' + alter
|
||||||
|
if equVersion is None or equVersion == '':
|
||||||
|
equVersion = '0'
|
||||||
try:
|
try:
|
||||||
character = importlib.import_module(module_name).classChange(equVersion)
|
character = importlib.import_module(module_name).classChange(equVersion)
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ class Skill:
|
|||||||
icon = icon.replace('$common', '/characters/common')
|
icon = icon.replace('$common', '/characters/common')
|
||||||
icon = icon.replace('$name', f'{self.name}')
|
icon = icon.replace('$name', f'{self.name}')
|
||||||
icon = icon.replace('$id', f'{self.id}')
|
icon = icon.replace('$id', f'{self.id}')
|
||||||
return icon
|
return f'{icon}.png'
|
||||||
|
|
||||||
def _calculate_lv(self):
|
def _calculate_lv(self):
|
||||||
return min(int((characterLv - self.learnLv) / self.rangeLv + 1), self.masterLv) if self._lv == 0 else self._lv
|
return min(int((characterLv - self.learnLv) / self.rangeLv + 1), self.masterLv) if self._lv == 0 else self._lv
|
||||||
|
|||||||
@@ -3,32 +3,32 @@
|
|||||||
"name": "swordman_male",
|
"name": "swordman_male",
|
||||||
"title": "鬼剑士(男)",
|
"title": "鬼剑士(男)",
|
||||||
"children": [
|
"children": [
|
||||||
{ "title": "极诣·剑魂", "name": "weapon_master", "open": true },
|
{ "title": "极诣·剑魂", "name": "weapon_master", "open": false },
|
||||||
{ "name": "soul_bender", "title": "极诣·鬼泣", "open": true },
|
{ "name": "soul_bender", "title": "极诣·鬼泣", "open": false },
|
||||||
{ "name": "berserker", "title": "极诣·狂战士", "open": true },
|
{ "name": "berserker", "title": "极诣·狂战士", "open": false },
|
||||||
{ "name": "asura", "title": "极诣·阿修罗", "open": true },
|
{ "name": "asura", "title": "极诣·阿修罗", "open": false },
|
||||||
{ "name": "ghostblade", "title": "极诣·剑影", "open": true }
|
{ "name": "ghostblade", "title": "极诣·剑影", "open": false }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "swordman_female",
|
"name": "swordman_female",
|
||||||
"title": "鬼剑士(女)",
|
"title": "鬼剑士(女)",
|
||||||
"children": [
|
"children": [
|
||||||
{ "name": "sword_master", "title": "极诣·驭剑士", "open": true },
|
{ "name": "sword_master", "title": "极诣·驭剑士", "open": false },
|
||||||
{ "name": "dark_templar", "title": "极诣·暗殿骑士", "open": true },
|
{ "name": "dark_templar", "title": "极诣·暗殿骑士", "open": false },
|
||||||
{ "name": "demon_slayer", "title": "极诣·契魔者", "open": true },
|
{ "name": "demon_slayer", "title": "极诣·契魔者", "open": false },
|
||||||
{ "name": "vegabond", "title": "极诣·流浪武士", "open": true },
|
{ "name": "vegabond", "title": "极诣·流浪武士", "open": false },
|
||||||
{ "name": "spectre", "title": "极诣·刃影", "open": true }
|
{ "name": "spectre", "title": "极诣·刃影", "open": false }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "fighter_male",
|
"name": "fighter_male",
|
||||||
"title": "格斗家(男)",
|
"title": "格斗家(男)",
|
||||||
"children": [
|
"children": [
|
||||||
{ "name": "nenmaster_male", "title": "归元·气功师", "open": true },
|
{ "name": "nenmaster_male", "title": "归元·气功师", "open": false },
|
||||||
{ "name": "striker_male", "title": "归元·散打", "open": true },
|
{ "name": "striker_male", "title": "归元·散打", "open": false },
|
||||||
{ "name": "brawler_male", "title": "归元·街霸", "open": true },
|
{ "name": "brawler_male", "title": "归元·街霸", "open": false },
|
||||||
{ "name": "grappler_male", "title": "归元·柔道家", "open": true },
|
{ "name": "grappler_male", "title": "归元·柔道家", "open": false },
|
||||||
{ "name": "empty", "title": "", "comment": "首页" }
|
{ "name": "empty", "title": "", "comment": "首页" }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -36,10 +36,10 @@
|
|||||||
"name": "fighter_female",
|
"name": "fighter_female",
|
||||||
"title": "格斗家(女)",
|
"title": "格斗家(女)",
|
||||||
"children": [
|
"children": [
|
||||||
{ "name": "nenmaster_female", "title": "归元·气功师", "open": true },
|
{ "name": "nenmaster_female", "title": "归元·气功师", "open": false },
|
||||||
{ "name": "striker_female", "title": "归元·散打", "open": true },
|
{ "name": "striker_female", "title": "归元·散打", "open": false },
|
||||||
{ "name": "brawler_female", "title": "归元·街霸", "open": true },
|
{ "name": "brawler_female", "title": "归元·街霸", "open": false },
|
||||||
{ "name": "grappler_female", "title": "归元·柔道家", "open": true },
|
{ "name": "grappler_female", "title": "归元·柔道家", "open": false },
|
||||||
{ "name": "empty", "title": "", "comment": "设置" }
|
{ "name": "empty", "title": "", "comment": "设置" }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -47,26 +47,26 @@
|
|||||||
"name": "gunner_male",
|
"name": "gunner_male",
|
||||||
"title": "神枪手(男)",
|
"title": "神枪手(男)",
|
||||||
"children": [
|
"children": [
|
||||||
{ "name": "ranger_male", "title": "重霄·漫游枪手", "open": true },
|
{ "name": "ranger_male", "title": "重霄·漫游枪手", "open": false },
|
||||||
{ "name": "launcher_male", "title": "重霄·枪炮师", "open": true },
|
{ "name": "launcher_male", "title": "重霄·枪炮师", "open": false },
|
||||||
{ "name": "mechanic_male", "title": "重霄·机械师", "open": true },
|
{ "name": "mechanic_male", "title": "重霄·机械师", "open": false },
|
||||||
{ "name": "spitfire_male", "title": "重霄·弹药专家", "open": true },
|
{ "name": "spitfire_male", "title": "重霄·弹药专家", "open": false },
|
||||||
{ "name": "assault", "title": "重霄·合金战士", "open": true }
|
{ "name": "assault", "title": "重霄·合金战士", "open": false }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "gunner_female",
|
"name": "gunner_female",
|
||||||
"title": "神枪手(女)",
|
"title": "神枪手(女)",
|
||||||
"children": [
|
"children": [
|
||||||
{ "name": "ranger_female", "title": "重霄·漫游枪手", "open": true },
|
{ "name": "ranger_female", "title": "重霄·漫游枪手", "open": false },
|
||||||
{ "name": "launcher_female", "title": "重霄·枪炮师", "open": true },
|
{ "name": "launcher_female", "title": "重霄·枪炮师", "open": false },
|
||||||
{ "name": "mechanic_female", "title": "重霄·机械师", "open": true },
|
{ "name": "mechanic_female", "title": "重霄·机械师", "open": false },
|
||||||
{ "name": "spitfire_female", "title": "重霄·弹药专家", "open": true },
|
{ "name": "spitfire_female", "title": "重霄·弹药专家", "open": true, "class": "GF.gunner_female.spitfire_female" },
|
||||||
{
|
{
|
||||||
"name": "sponsor",
|
"name": "sponsor",
|
||||||
"url": "https://bbs.colg.cn",
|
"url": "https://bbs.colg.cn",
|
||||||
"title": "",
|
"title": "",
|
||||||
"open": true
|
"open": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -74,25 +74,25 @@
|
|||||||
"name": "mage_male",
|
"name": "mage_male",
|
||||||
"title": "魔法师(男)",
|
"title": "魔法师(男)",
|
||||||
"children": [
|
"children": [
|
||||||
{ "name": "elemental_bomber", "title": "知源·元素爆破师", "open": true },
|
{ "name": "elemental_bomber", "title": "知源·元素爆破师", "open": false },
|
||||||
{ "name": "glacial_master", "title": "知源·冰结师", "open": true },
|
{ "name": "glacial_master", "title": "知源·冰结师", "open": false },
|
||||||
{ "name": "blood_mage", "title": "知源·血法师", "open": true },
|
{ "name": "blood_mage", "title": "知源·血法师", "open": false },
|
||||||
{ "name": "swift_master", "title": "知源·逐风者", "open": true },
|
{ "name": "swift_master", "title": "知源·逐风者", "open": false },
|
||||||
{ "name": "dimension_walker", "title": "知源·次元行者", "open": true }
|
{ "name": "dimension_walker", "title": "知源·次元行者", "open": false }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "mage_female",
|
"name": "mage_female",
|
||||||
"title": "魔法师(女)",
|
"title": "魔法师(女)",
|
||||||
"children": [
|
"children": [
|
||||||
{ "name": "elementalist", "title": "知源·元素师", "open": true },
|
{ "name": "elementalist", "title": "知源·元素师", "open": false },
|
||||||
{ "name": "summoner", "title": "知源·召唤师", "open": true },
|
{ "name": "summoner", "title": "知源·召唤师", "open": false },
|
||||||
{ "name": "battle_mage", "title": "知源·战斗法师", "open": true },
|
{ "name": "battle_mage", "title": "知源·战斗法师", "open": false },
|
||||||
{ "name": "witch", "title": "知源·魔道学者", "open": true },
|
{ "name": "witch", "title": "知源·魔道学者", "open": false },
|
||||||
{
|
{
|
||||||
"name": "enchantress",
|
"name": "enchantress",
|
||||||
"title": "知源·小魔女",
|
"title": "知源·小魔女",
|
||||||
"open": true,
|
"open": false,
|
||||||
"options": [
|
"options": [
|
||||||
{ "name": "default", "title": "奶", "class": "enchantress" },
|
{ "name": "default", "title": "奶", "class": "enchantress" },
|
||||||
{ "name": "default", "title": "输出", "class": "enchantress_carry" }
|
{ "name": "default", "title": "输出", "class": "enchantress_carry" }
|
||||||
@@ -107,15 +107,15 @@
|
|||||||
{
|
{
|
||||||
"name": "crusader_male",
|
"name": "crusader_male",
|
||||||
"title": "神启·圣骑士",
|
"title": "神启·圣骑士",
|
||||||
"open": true,
|
"open": false,
|
||||||
"options": [
|
"options": [
|
||||||
{ "name": "default", "title": "奶", "class": "crusader_male" },
|
{ "name": "default", "title": "奶", "class": "crusader_male" },
|
||||||
{ "name": "default", "title": "审判", "class": "crusader_male_carry" }
|
{ "name": "default", "title": "审判", "class": "crusader_male_carry" }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{ "name": "infighter", "title": "神启·蓝拳圣使", "open": true },
|
{ "name": "infighter", "title": "神启·蓝拳圣使", "open": false },
|
||||||
{ "name": "exorcist", "title": "神启·驱魔师", "open": true },
|
{ "name": "exorcist", "title": "神启·驱魔师", "open": false },
|
||||||
{ "name": "avenger", "title": "神启·复仇者", "open": true },
|
{ "name": "avenger", "title": "神启·复仇者", "open": false },
|
||||||
{ "name": "empty", "title": "" }
|
{ "name": "empty", "title": "" }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -126,7 +126,7 @@
|
|||||||
{
|
{
|
||||||
"name": "crusader_female",
|
"name": "crusader_female",
|
||||||
"title": "神启·圣骑士",
|
"title": "神启·圣骑士",
|
||||||
"open": true,
|
"open": false,
|
||||||
"options": [
|
"options": [
|
||||||
{ "name": "default", "title": "奶", "class": "crusader_female" },
|
{ "name": "default", "title": "奶", "class": "crusader_female" },
|
||||||
{
|
{
|
||||||
@@ -136,9 +136,9 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{ "name": "inquistor", "title": "神启·异端审判者", "open": true },
|
{ "name": "inquistor", "title": "神启·异端审判者", "open": false },
|
||||||
{ "name": "sorceress", "title": "神启·巫女", "open": true },
|
{ "name": "sorceress", "title": "神启·巫女", "open": false },
|
||||||
{ "name": "mistress", "title": "神启·诱魔者", "open": true },
|
{ "name": "mistress", "title": "神启·诱魔者", "open": false },
|
||||||
{ "name": "empty", "title": "" }
|
{ "name": "empty", "title": "" }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -146,10 +146,10 @@
|
|||||||
"name": "thief",
|
"name": "thief",
|
||||||
"title": "暗夜使者",
|
"title": "暗夜使者",
|
||||||
"children": [
|
"children": [
|
||||||
{ "name": "rogue", "title": "隐夜·刺客", "open": true },
|
{ "name": "rogue", "title": "隐夜·刺客", "open": false },
|
||||||
{ "name": "necro", "title": "隐夜·死灵术士", "open": true },
|
{ "name": "necro", "title": "隐夜·死灵术士", "open": false },
|
||||||
{ "name": "kunoichi", "title": "隐夜·忍者", "open": true },
|
{ "name": "kunoichi", "title": "隐夜·忍者", "open": false },
|
||||||
{ "name": "shadow_dancer", "title": "隐夜·影舞者", "open": true },
|
{ "name": "shadow_dancer", "title": "隐夜·影舞者", "open": false },
|
||||||
{ "name": "empty", "title": "" }
|
{ "name": "empty", "title": "" }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -157,10 +157,10 @@
|
|||||||
"name": "knight",
|
"name": "knight",
|
||||||
"title": "守护者",
|
"title": "守护者",
|
||||||
"children": [
|
"children": [
|
||||||
{ "name": "elven_knight", "title": "皓曦·精灵骑士", "open": true },
|
{ "name": "elven_knight", "title": "皓曦·精灵骑士", "open": false },
|
||||||
{ "name": "chaos", "title": "皓曦·混沌魔灵", "open": true },
|
{ "name": "chaos", "title": "皓曦·混沌魔灵", "open": false },
|
||||||
{ "name": "paladin", "title": "皓曦·帕拉丁", "open": true },
|
{ "name": "paladin", "title": "皓曦·帕拉丁", "open": false },
|
||||||
{ "name": "dragon_knight", "title": "皓曦·龙骑士", "open": true },
|
{ "name": "dragon_knight", "title": "皓曦·龙骑士", "open": false },
|
||||||
{ "name": "empty", "title": "" }
|
{ "name": "empty", "title": "" }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -168,10 +168,10 @@
|
|||||||
"name": "demonic_lancer",
|
"name": "demonic_lancer",
|
||||||
"title": "魔枪士",
|
"title": "魔枪士",
|
||||||
"children": [
|
"children": [
|
||||||
{ "name": "vanguard", "title": "千魂·征战者", "open": true },
|
{ "name": "vanguard", "title": "千魂·征战者", "open": false },
|
||||||
{ "name": "skirmisher", "title": "千魂·决战者", "open": true },
|
{ "name": "skirmisher", "title": "千魂·决战者", "open": false },
|
||||||
{ "name": "dragoon", "title": "千魂·狩猎者", "open": true },
|
{ "name": "dragoon", "title": "千魂·狩猎者", "open": false },
|
||||||
{ "name": "impaler", "title": "千魂·暗枪士", "open": true },
|
{ "name": "impaler", "title": "千魂·暗枪士", "open": false },
|
||||||
{ "name": "empty", "title": "" }
|
{ "name": "empty", "title": "" }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -179,10 +179,10 @@
|
|||||||
"name": "gunblader",
|
"name": "gunblader",
|
||||||
"title": "枪剑士",
|
"title": "枪剑士",
|
||||||
"children": [
|
"children": [
|
||||||
{ "name": "hitman", "title": "苍暮·暗刃", "open": true },
|
{ "name": "hitman", "title": "苍暮·暗刃", "open": false },
|
||||||
{ "name": "agent", "title": "苍暮·特工", "open": true },
|
{ "name": "agent", "title": "苍暮·特工", "open": false },
|
||||||
{ "name": "trouble_shooter", "title": "苍暮·战线佣兵", "open": true },
|
{ "name": "trouble_shooter", "title": "苍暮·战线佣兵", "open": false },
|
||||||
{ "name": "specialist", "title": "苍暮·源能专家", "open": true },
|
{ "name": "specialist", "title": "苍暮·源能专家", "open": false },
|
||||||
{ "name": "empty", "title": "" }
|
{ "name": "empty", "title": "" }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -190,10 +190,10 @@
|
|||||||
"name": "archer",
|
"name": "archer",
|
||||||
"title": "弓箭手",
|
"title": "弓箭手",
|
||||||
"children": [
|
"children": [
|
||||||
{ "name": "muse", "title": "聆风·缪斯", "open": true },
|
{ "name": "muse", "title": "聆风·缪斯", "open": false },
|
||||||
{ "name": "traveler", "title": "聆风·旅人", "open": true },
|
{ "name": "traveler", "title": "聆风·旅人", "open": false },
|
||||||
{ "name": "hunter", "title": "聆风·猎人", "open": true },
|
{ "name": "hunter", "title": "聆风·猎人", "open": false },
|
||||||
{ "name": "vigilante", "title": "聆风·妖护使", "open": true },
|
{ "name": "vigilante", "title": "聆风·妖护使", "open": false },
|
||||||
{ "name": "empty", "title": "" }
|
{ "name": "empty", "title": "" }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -201,8 +201,8 @@
|
|||||||
"name": "extra",
|
"name": "extra",
|
||||||
"title": "外传",
|
"title": "外传",
|
||||||
"children": [
|
"children": [
|
||||||
{ "name": "creator", "title": "知源·缔造者", "open": true },
|
{ "name": "creator", "title": "知源·缔造者", "open": false },
|
||||||
{ "name": "dark_knight", "title": "极诣·黑暗武士", "open": true },
|
{ "name": "dark_knight", "title": "极诣·黑暗武士", "open": false },
|
||||||
{ "name": "empty", "title": "" },
|
{ "name": "empty", "title": "" },
|
||||||
{ "name": "empty", "title": "" },
|
{ "name": "empty", "title": "" },
|
||||||
{ "name": "empty", "title": "" }
|
{ "name": "empty", "title": "" }
|
||||||
|
|||||||
+1
-1
@@ -20,6 +20,6 @@ if __name__ == '__main__':
|
|||||||
|
|
||||||
application.include_router(api_router)
|
application.include_router(api_router)
|
||||||
|
|
||||||
uvicorn.run(application, host='127.0.0.1', port=config.PORT)
|
uvicorn.run(app = application, host='127.0.0.1', port=config.PORT)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import type { AxiosInstance, AxiosResponse } from 'axios'
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { h } from 'vue'
|
import { h } from 'vue'
|
||||||
import { gzip, ungzip } from 'pako'
|
import { gzip, ungzip } from 'pako'
|
||||||
|
import { useInfoStore } from '@/stores'
|
||||||
// import { useAppStore, useConfigStore } from '@/store'
|
// import { useAppStore, useConfigStore } from '@/store'
|
||||||
// import { useDialog } from '@/components/hooks/dialog'
|
// import { useDialog } from '@/components/hooks/dialog'
|
||||||
|
|
||||||
@@ -58,19 +59,12 @@ export function defineRequest<T>(fn: (ax: AxiosInstance) => T) {
|
|||||||
// const token = configStore.token
|
// const token = configStore.token
|
||||||
// const uid = useAppStore().uid
|
// const uid = useAppStore().uid
|
||||||
|
|
||||||
const token = 'test'
|
const token = useInfoStore().token
|
||||||
|
|
||||||
if (token) {
|
if (token) {
|
||||||
request.headers['Access-Token'] = token
|
request.headers['Access-Token'] = token
|
||||||
}
|
}
|
||||||
|
|
||||||
// 在网页端,会添加token
|
|
||||||
const accessToken = localStorage.getItem('dcalc/access_token')
|
|
||||||
|
|
||||||
if (accessToken) {
|
|
||||||
request.headers.Authorization = `Bearer ${accessToken}`
|
|
||||||
}
|
|
||||||
|
|
||||||
return request
|
return request
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
|
|||||||
@@ -1,10 +1,19 @@
|
|||||||
import { defineRequest } from '../common'
|
import { defineRequest } from '../common'
|
||||||
import type { IAdventureInfo } from './type'
|
import type { IAdventureInfo, ICharacterInfo } from './type'
|
||||||
|
|
||||||
export default defineRequest((request) => {
|
export default defineRequest((request) => {
|
||||||
return {
|
return {
|
||||||
adventures() {
|
async adventures() {
|
||||||
return request.get<IAdventureInfo[]>('/adventure').then((res) => res.data)
|
const res = await request.get<IAdventureInfo[]>('/adventure')
|
||||||
|
return res.data
|
||||||
|
},
|
||||||
|
async createToken(alter: string, equVersion?: string) {
|
||||||
|
const res = await request.get<string>(`/token/get/${alter}`, { params: { equVersion } })
|
||||||
|
return res.data
|
||||||
|
},
|
||||||
|
async characterInfo() {
|
||||||
|
const res = await request.get<ICharacterInfo>('/character')
|
||||||
|
return res.data
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -3,20 +3,6 @@ export interface IAdventureInfo {
|
|||||||
name: string
|
name: string
|
||||||
children: IAlterInfo[]
|
children: IAlterInfo[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ITools {
|
|
||||||
name: string
|
|
||||||
tooltips: string
|
|
||||||
link: string
|
|
||||||
end?: Date
|
|
||||||
target: '_blank' | '_self'
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IMonster {
|
|
||||||
id: number
|
|
||||||
name: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IAlterOption {
|
export interface IAlterOption {
|
||||||
name: string
|
name: string
|
||||||
title: string
|
title: string
|
||||||
@@ -31,4 +17,27 @@ export interface IAlterInfo {
|
|||||||
options?: IAlterOption[]
|
options?: IAlterOption[]
|
||||||
open?: boolean
|
open?: boolean
|
||||||
comment?: string
|
comment?: string
|
||||||
|
class?:string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ICharacterInfo {
|
||||||
|
alter: string
|
||||||
|
name: string
|
||||||
|
equVersion: string
|
||||||
|
equips: IEquipment[]
|
||||||
|
weapons: string[]
|
||||||
|
skills: ISkill[]
|
||||||
|
suits: ISuit[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IEquipment {}
|
||||||
|
|
||||||
|
export interface ISkill {
|
||||||
|
icon: string
|
||||||
|
name: string
|
||||||
|
id: number
|
||||||
|
learnLv:number
|
||||||
|
positon:number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ISuit {}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import '@/style/index.scss'
|
import '@/style/index.scss'
|
||||||
|
|
||||||
import { createApp } from 'vue'
|
import { createApp } from 'vue'
|
||||||
import { createPinia } from 'pinia'
|
import { pinia } from "@/stores"
|
||||||
|
|
||||||
import App from '@/pages/IndexView.vue'
|
import App from '@/pages/IndexView.vue'
|
||||||
|
|
||||||
import router from './router'
|
import router from './router'
|
||||||
@@ -13,7 +14,7 @@ document.body.appendChild(appContainer)
|
|||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
|
|
||||||
app.use(createPinia())
|
app.use(pinia)
|
||||||
app.use(router)
|
app.use(router)
|
||||||
|
|
||||||
app.mount(appContainer)
|
app.mount(appContainer)
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<template>
|
||||||
|
<div class="h-90vh w-560px overflow-y-auto overflow-x-hidden">
|
||||||
|
<SkillTree></SkillTree>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup name="Index">
|
||||||
|
import { useInfoStore } from '@/stores/info'
|
||||||
|
import { getImageURL } from '@/utils/images'
|
||||||
|
import SkillTree from './Skill/SkillTree.vue';
|
||||||
|
const props = defineProps<{
|
||||||
|
alter: string
|
||||||
|
}>()
|
||||||
|
const infoStore = useInfoStore()
|
||||||
|
onMounted(() => {
|
||||||
|
infoStore.createCharacter(props.alter, '0')
|
||||||
|
})
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
<template>
|
||||||
|
<div class="relative w-550px h-auto">
|
||||||
|
<template v-for="item in infoStore.skills" :key="item.id">
|
||||||
|
<div
|
||||||
|
class="absolute w-34px h-auto flex flex-col gap-2px py-2px items-center bg-#2c2d2c rounded-2px"
|
||||||
|
:style="skillPositon(item.learnLv, item.positon)"
|
||||||
|
>
|
||||||
|
<img class="w-30px h-30px" :src="getImageURL(item.icon)" :alt="item.name" />
|
||||||
|
<div class="flex-1 bg-black text-white">100级</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-for="lv of 21" :key="lv">
|
||||||
|
<div class="skill-tree-line flex items-center px-20px text-#373837">
|
||||||
|
{{ lv % 2 === 1 ? Math.max(1, (lv - 1) * 5) :'' }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { useInfoStore } from '@/stores'
|
||||||
|
import { getImageURL } from '@/utils/images'
|
||||||
|
|
||||||
|
const infoStore = useInfoStore()
|
||||||
|
|
||||||
|
const skillPositon = (learnLv: number, positon: number) => {
|
||||||
|
return {
|
||||||
|
positon: 'absolute',
|
||||||
|
left: `${positon * 50 + 50}px`,
|
||||||
|
top: `${Math.floor(learnLv / 5) * 80 + 8}px`,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.skill-tree-line {
|
||||||
|
height: 80px;
|
||||||
|
width: auto;
|
||||||
|
&:nth-child(n + 1) {
|
||||||
|
background-color: #000000;
|
||||||
|
}
|
||||||
|
&:nth-child(2n + 1) {
|
||||||
|
background-color: #202020;
|
||||||
|
backdrop-filter: blur(1px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -24,82 +24,22 @@ export default defineComponent(async () => {
|
|||||||
// 获取角色相关信息,判定是否开放
|
// 获取角色相关信息,判定是否开放
|
||||||
function choose_job(child: IAlterInfo) {
|
function choose_job(child: IAlterInfo) {
|
||||||
return async () => {
|
return async () => {
|
||||||
// if (child.comment == '首页') {
|
if (child.comment == '首页') {
|
||||||
// return openUrl('https://dnftools.com/')
|
return window.open("https://dnftools.com","_blank")
|
||||||
// }
|
}
|
||||||
// if (child.comment == '设置') {
|
if (child.name == 'sponsor') {
|
||||||
// return openUrl('/set', { width: 600, height: 500, scale: zoom.value })
|
return window.open((child.url ?? ''),"_blank")
|
||||||
// }
|
}
|
||||||
// if (ignores.includes(child.name)) {
|
if (child.open) {
|
||||||
// return
|
const options = child.options ?? []
|
||||||
// }
|
if (options.length > 0) {
|
||||||
// if (child.name == 'sponsor') {
|
return
|
||||||
// return openUrl(child.url ?? '')
|
}
|
||||||
// }
|
else{
|
||||||
// if (child.open || import.meta.env.DEV) {
|
return window.open("/character/" + (child.class || child.name),"_self")
|
||||||
// const options = child.options ?? []
|
}
|
||||||
// if (options.length > 0) {
|
|
||||||
// const id = randomId()
|
|
||||||
// return await show({
|
|
||||||
// // id,
|
|
||||||
// scale: zoom.value,
|
|
||||||
// content: '请选择职业平衡版本',
|
|
||||||
// action: () => {
|
|
||||||
// return (
|
|
||||||
// <>
|
|
||||||
// <div class="flex items-center justify-around flex-wrap" style="width:200px">
|
|
||||||
// {renderList(options, (option) =>
|
|
||||||
// !option.class ? (
|
|
||||||
// <calc-button
|
|
||||||
// class="!w-40% !mb-2"
|
|
||||||
// onClick={() => {
|
|
||||||
// openUrl('/character', {
|
|
||||||
// query: { alter: child.name },
|
|
||||||
// width: 1100,
|
|
||||||
// height: 775,
|
|
||||||
// scale: zoom.value,
|
|
||||||
// })
|
|
||||||
// close(id, 'ok')
|
|
||||||
// }}
|
|
||||||
// >
|
|
||||||
// {option.title}
|
|
||||||
// </calc-button>
|
|
||||||
// ) : (
|
|
||||||
// <calc-button
|
|
||||||
// class="!w-40% !mb-2"
|
|
||||||
// onClick={() => {
|
|
||||||
// openUrl('/character', {
|
|
||||||
// query: { alter: option.class ?? '' },
|
|
||||||
// width: 1100,
|
|
||||||
// height: 775,
|
|
||||||
// scale: zoom.value,
|
|
||||||
// })
|
|
||||||
// close(id, 'ok')
|
|
||||||
// }}
|
|
||||||
// >
|
|
||||||
// {option.title}
|
|
||||||
// </calc-button>
|
|
||||||
// ),
|
|
||||||
// )}
|
|
||||||
// </div>
|
|
||||||
// </>
|
|
||||||
// )
|
|
||||||
// },
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// return openUrl('/character', {
|
|
||||||
// query: { alter: child.name },
|
|
||||||
// width: 1100,
|
|
||||||
// height: 775,
|
|
||||||
// title: child.title,
|
|
||||||
// scale: zoom.value,
|
|
||||||
// })
|
|
||||||
// } else {
|
|
||||||
// return alert({
|
|
||||||
// content: '未开放的角色!',
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// router.push("/character/" + alter)
|
// router.push("/character/" + alter)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7,8 +7,14 @@ const routes: RouteRecordRaw[] = [
|
|||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
name: 'home',
|
name: 'home',
|
||||||
component: defineAsyncComponent(() => import('@/pages/Home/HomeView.vue')),
|
component: defineAsyncComponent(() => import('@/pages/Home/Index.vue')),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path:'/character/:alter',
|
||||||
|
name:'character',
|
||||||
|
props: true,
|
||||||
|
component: defineAsyncComponent(() => import('@/pages/Character/Index.vue')),
|
||||||
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
import {defineStore} from 'pinia'
|
||||||
|
|
||||||
|
const config = defineStore('config', ()=>{
|
||||||
|
})
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
import { ref, computed } from 'vue'
|
|
||||||
import { defineStore } from 'pinia'
|
|
||||||
|
|
||||||
export const useCounterStore = defineStore('counter', () => {
|
|
||||||
const count = ref(0)
|
|
||||||
const doubleCount = computed(() => count.value * 2)
|
|
||||||
function increment() {
|
|
||||||
count.value++
|
|
||||||
}
|
|
||||||
|
|
||||||
return { count, doubleCount, increment }
|
|
||||||
})
|
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import { createPinia } from "pinia"
|
||||||
|
|
||||||
|
export * from "./info"
|
||||||
|
|
||||||
|
export const pinia = createPinia()
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import api from "@/api"
|
||||||
|
import type { ICharacterInfo } from "@/api/info/type"
|
||||||
|
import { defineStore } from "pinia"
|
||||||
|
|
||||||
|
export const useInfoStore = defineStore("infoStore", ()=>{
|
||||||
|
|
||||||
|
const token = ref<string>("")
|
||||||
|
const infos = ref<ICharacterInfo | null>(null)
|
||||||
|
|
||||||
|
const skills = computed(()=>infos.value?.skills ?? [])
|
||||||
|
|
||||||
|
const equips = computed(()=>infos.value?.equips ?? [])
|
||||||
|
|
||||||
|
const suits = computed(()=>infos.value?.suits ?? [])
|
||||||
|
|
||||||
|
const createCharacter = async (alter: string, equVersion?: string) => {
|
||||||
|
token.value = await api.createToken(alter, equVersion)
|
||||||
|
infos.value = await api.characterInfo()
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
token,
|
||||||
|
infos,
|
||||||
|
skills,
|
||||||
|
equips,
|
||||||
|
suits,
|
||||||
|
createCharacter,
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
let baseURL = '/img'
|
let baseURL = 'https://image.dnftools.com'
|
||||||
|
|
||||||
// 避免远程开发的时候冲突
|
// 避免远程开发的时候冲突
|
||||||
if (process.env.NODE_ENV == 'development') {
|
if (process.env.NODE_ENV == 'development') {
|
||||||
@@ -10,5 +10,6 @@ if (import.meta.env.MODE == 'web' || import.meta.env.MODE == 'show') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const getImageURL = (image: string) => {
|
export const getImageURL = (image: string) => {
|
||||||
return `${baseURL}/${image}`
|
image = image.startsWith('/') ? image : `/${image}`
|
||||||
|
return `${baseURL}${image}`
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
+1
-1
@@ -9,7 +9,7 @@ const ImageServer = http.createServer((req, res) => {
|
|||||||
// 图片存储的文件夹路径
|
// 图片存储的文件夹路径
|
||||||
const directoryPath = path.join(__dirname, '../images');
|
const directoryPath = path.join(__dirname, '../images');
|
||||||
// 请求的图片文件名
|
// 请求的图片文件名
|
||||||
const filePath = path.join(directoryPath, req.url);
|
const filePath = path.join(directoryPath, decodeURIComponent(req.url));
|
||||||
// 确保文件存在且是文件,不是目录
|
// 确保文件存在且是文件,不是目录
|
||||||
fs.access(filePath, fs.constants.F_OK | fs.constants.R_OK, (err) => {
|
fs.access(filePath, fs.constants.F_OK | fs.constants.R_OK, (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|||||||
Reference in New Issue
Block a user