♻️ 重新建表以存储新格式数据

This commit is contained in:
目棃
2024-08-16 14:53:02 +08:00
parent 27e22acdf6
commit 68f91035df
9 changed files with 254 additions and 550 deletions

View File

@@ -9,7 +9,7 @@
<div class="tua-abl-mid"> <div class="tua-abl-mid">
<div class="tua-abl-fetter"> <div class="tua-abl-fetter">
<img src="/icon/material/105.webp" alt="fetter" /> <img src="/icon/material/105.webp" alt="fetter" />
<span>{{ props.modelValue.base.fetter }}</span> <span>{{ props.modelValue.avatar.fetter }}</span>
</div> </div>
<div class="tua-abl-other"> <div class="tua-abl-other">
<span v-if="!isFetterMax"> <span v-if="!isFetterMax">
@@ -41,8 +41,8 @@
<img :src="`/icon/relic/${index + 1}.webp`" alt="relic" v-if="relic === false" /> <img :src="`/icon/relic/${index + 1}.webp`" alt="relic" v-if="relic === false" />
<img :src="relic.icon" alt="relic" v-if="relic !== false" /> <img :src="relic.icon" alt="relic" v-if="relic !== false" />
</div> </div>
<div class="tua-rl-bg" v-if="relic !== false"> <div class="tua-rl-bg">
<img :src="`/icon/bg/${relic.rarity}-Star.webp`" alt="bg" /> <img :src="`/icon/bg/${relic.rarity}-Star.webp`" alt="bg" v-if="relic !== false" />
</div> </div>
<div :class="`tua-rl-relic rarity${relic.rarity}`" v-if="relic !== false"> <div :class="`tua-rl-relic rarity${relic.rarity}`" v-if="relic !== false">
{{ relic.level }} {{ relic.level }}
@@ -51,10 +51,18 @@
<!-- 右侧数值及加成 --> <!-- 右侧数值及加成 -->
<div class="tua-relic-right"> <div class="tua-relic-right">
<div class="tua-relic-name"> <div class="tua-relic-name">
{{ relic === false ? getRelicName(index) : getPropName(relic) }} {{ relic === false ? getRelicName(index) : relic.main_property.value }}
</div>
<div class="tua-relic-prop" v-if="relic !== false">
<div v-if="getPropName(relic) !== false">
<img
v-if="getPropName(relic).icon !== ''"
:src="getPropName(relic).icon"
alt="prop"
:title="getPropName(relic).name"
/>
<span v-else>{{ getPropName(relic)?.name }}</span>
</div> </div>
<div class="tua-relic-prop">
{{ relic !== false ? relic.main_property.value : "" }}
</div> </div>
</div> </div>
</div> </div>
@@ -70,7 +78,7 @@ import { getZhElement } from "../../utils/toolFunc.js";
import TItembox, { TItemBoxData } from "../main/t-itembox.vue"; import TItembox, { TItemBoxData } from "../main/t-itembox.vue";
interface TuaAvatarBoxProps { interface TuaAvatarBoxProps {
modelValue: TGApp.Game.Avatar.DetailList; modelValue: TGApp.Sqlite.Character.UserRole;
} }
type FixedLenArr<T, N extends number> = [T, ...T[]] & { length: N }; type FixedLenArr<T, N extends number> = [T, ...T[]] & { length: N };
@@ -80,7 +88,7 @@ const props = defineProps<TuaAvatarBoxProps>();
const userStore = useUserStore(); const userStore = useUserStore();
const avatarBox = computed<TItemBoxData>(() => { const avatarBox = computed<TItemBoxData>(() => {
const avatar = props.modelValue.base; const avatar = props.modelValue.avatar;
return { return {
size: "100px", size: "100px",
height: "120px", height: "120px",
@@ -118,10 +126,10 @@ const weaponBox = computed<TItemBoxData>(() => {
}; };
}); });
const isFetterMax = computed<boolean>(() => { const isFetterMax = computed<boolean>(() => {
if (props.modelValue.base.id === 10000005 || props.modelValue.base.id === 10000007) { if (props.modelValue.avatar.id === 10000005 || props.modelValue.avatar.id === 10000007) {
return true; return true;
} }
return props.modelValue.base.fetter === 10; return props.modelValue.avatar.fetter === 10;
}); });
const skills = computed<TGApp.Game.Avatar.Skill[]>(() => { const skills = computed<TGApp.Game.Avatar.Skill[]>(() => {
return props.modelValue.skills.filter((skill) => skill.skill_type === 1); return props.modelValue.skills.filter((skill) => skill.skill_type === 1);
@@ -141,8 +149,8 @@ const nameCard = ref<string | false>(false);
onMounted(async () => { onMounted(async () => {
if (!props.modelValue) return; if (!props.modelValue) return;
if (props.modelValue.base.id !== 10000005 && props.modelValue.base.id !== 10000007) { if (props.modelValue.avatar.id !== 10000005 && props.modelValue.avatar.id !== 10000007) {
const role = await TGSqlite.getAppCharacter(props.modelValue.base.id); const role = await TGSqlite.getAppCharacter(props.modelValue.avatar.id);
nameCard.value = `/source/nameCard/profile/${role.nameCard}.webp`; nameCard.value = `/source/nameCard/profile/${role.nameCard}.webp`;
} else { } else {
nameCard.value = "/source/nameCard/profile/原神·印象.webp"; nameCard.value = "/source/nameCard/profile/原神·印象.webp";
@@ -154,9 +162,8 @@ function getRelicName(pos: number): string {
return nameList[pos]; return nameList[pos];
} }
function getPropName(relic: TGApp.Game.Avatar.Relic): string { function getPropName(relic: TGApp.Game.Avatar.Relic): TGApp.Game.Avatar.PropMapItem | false {
const prop = userStore.getProp(relic.main_property.property_type); return userStore.getProp(relic.main_property.property_type);
return prop === false ? "" : prop.name;
} }
</script> </script>
<style lang="css" scoped> <style lang="css" scoped>
@@ -307,8 +314,7 @@ function getPropName(relic: TGApp.Game.Avatar.Relic): string {
.tua-abr-relic { .tua-abr-relic {
display: flex; display: flex;
width: 180px; width: 120px;
height: 60px;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
column-gap: 5px; column-gap: 5px;
@@ -341,13 +347,15 @@ function getPropName(relic: TGApp.Game.Avatar.Relic): string {
} }
.tua-rl-bg { .tua-rl-bg {
overflow: hidden;
width: 100%; width: 100%;
height: 100%; height: 100%;
border-radius: 50%;
background: var(--box-bg-3);
img { img {
width: 100%; width: 100%;
height: 100%; height: 100%;
border-radius: 50%;
} }
} }
@@ -398,7 +406,6 @@ function getPropName(relic: TGApp.Game.Avatar.Relic): string {
flex-direction: column; flex-direction: column;
align-items: flex-end; align-items: flex-end;
justify-content: center; justify-content: center;
row-gap: 5px;
} }
.tua-relic-name { .tua-relic-name {
@@ -408,7 +415,15 @@ function getPropName(relic: TGApp.Game.Avatar.Relic): string {
} }
.tua-relic-prop { .tua-relic-prop {
display: inline-flex;
color: var(--box-text-4); color: var(--box-text-4);
font-size: 12px; font-size: 12px;
img {
width: 20px;
height: 20px;
filter: invert(0.5) contrast(1) drop-shadow(0 0 5px var(--common-shadow-4));
object-fit: contain;
}
} }
</style> </style>

View File

@@ -9,19 +9,13 @@
<span v-else> 暂无数据 </span> <span v-else> 暂无数据 </span>
</div> </div>
<div class="uc-top-btns" data-html2canvas-ignore> <div class="uc-top-btns" data-html2canvas-ignore>
<v-btn class="uc-top-btn" @click="refreshRoles()"> <v-btn class="uc-top-btn" @click="refresh()">
<template #prepend> <template #prepend>
<v-icon>mdi-refresh</v-icon> <v-icon>mdi-refresh</v-icon>
</template> </template>
更新角色数据 刷新
</v-btn> </v-btn>
<v-btn class="uc-top-btn" @click="refreshTalent()"> <v-btn class="uc-top-btn" @click="share()">
<template #prepend>
<v-icon>mdi-refresh</v-icon>
</template>
更新天赋数据
</v-btn>
<v-btn class="uc-top-btn" @click="shareRoles()">
<template #prepend> <template #prepend>
<v-icon>mdi-share</v-icon> <v-icon>mdi-share</v-icon>
</template> </template>
@@ -30,7 +24,7 @@
</div> </div>
</div> </div>
<div class="uc-grid"> <div class="uc-grid">
<TucRoleBox <TuaAvatarBox
v-for="(role, index) in roleList" v-for="(role, index) in roleList"
:key="index" :key="index"
:model-value="role" :model-value="role"
@@ -38,31 +32,15 @@
/> />
</div> </div>
</div> </div>
<TucDetailOverlay
v-if="!detailDev"
v-model="visible"
@clickL="clickOverlay('left')"
@clickR="clickOverlay('right')"
:data-val="dataVal"
/>
<DucDetailOverlay
v-if="detailDev"
v-model="visible"
@clickL="clickOverlay('left')"
@clickR="clickOverlay('right')"
:data-val="dataVal"
/>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { storeToRefs } from "pinia"; import { storeToRefs } from "pinia";
import { onBeforeMount, onMounted, ref } from "vue"; import { onBeforeMount, onMounted, ref } from "vue";
import DucDetailOverlay from "../../components/devCharacter/duc-detail-overlay.vue";
import showSnackbar from "../../components/func/snackbar.js"; import showSnackbar from "../../components/func/snackbar.js";
import ToLoading from "../../components/overlay/to-loading.vue"; import ToLoading from "../../components/overlay/to-loading.vue";
import TucDetailOverlay from "../../components/userCharacter/tuc-detail-overlay.vue"; import TuaAvatarBox from "../../components/userAvatar/tua-avatar-box.vue";
import TucRoleBox from "../../components/userCharacter/tuc-role-box.vue"; import TSUserAvatar from "../../plugins/Sqlite/modules/userAvatar.js";
import TGSqlite from "../../plugins/Sqlite/index.js";
import { useUserStore } from "../../store/modules/user.js"; import { useUserStore } from "../../store/modules/user.js";
import TGLogger from "../../utils/TGLogger.js"; import TGLogger from "../../utils/TGLogger.js";
import { generateShareImg } from "../../utils/TGShare.js"; import { generateShareImg } from "../../utils/TGShare.js";
@@ -87,23 +65,6 @@ const dataVal = ref<TGApp.Sqlite.Character.UserRole>(<TGApp.Sqlite.Character.Use
const selectIndex = ref(0); const selectIndex = ref(0);
const detailDev = ref(true); const detailDev = ref(true);
function clickOverlay(pos: "left" | "right") {
if (pos === "left") {
if (selectIndex.value === 0) {
selectIndex.value = roleList.value.length - 1;
} else {
selectIndex.value -= 1;
}
} else {
if (selectIndex.value === roleList.value.length - 1) {
selectIndex.value = 0;
} else {
selectIndex.value += 1;
}
}
dataVal.value = roleList.value[selectIndex.value];
}
onBeforeMount(() => { onBeforeMount(() => {
if (userStore.account.value) { if (userStore.account.value) {
user.value = userStore.account.value; user.value = userStore.account.value;
@@ -114,7 +75,7 @@ onMounted(async () => {
await TGLogger.Info("[Character][onMounted] 进入角色页面"); await TGLogger.Info("[Character][onMounted] 进入角色页面");
loadingTitle.value = "正在获取角色数据"; loadingTitle.value = "正在获取角色数据";
loading.value = true; loading.value = true;
await loadRole(); await load();
loading.value = false; loading.value = false;
}); });
@@ -125,13 +86,13 @@ function switchOld(): void {
}); });
} }
async function loadRole(): Promise<void> { async function load(): Promise<void> {
if (!user.value) return; if (!user.value) return;
const roleData = await TGSqlite.getUserCharacter(user.value.gameUid); const roleData = await TSUserAvatar.getAvatars(user.value.gameUid);
if (roleData !== false) {
roleData.sort((a, b) => { roleData.sort((a, b) => {
if (a.star !== b.star) return b.star - a.star; if (a.avatar.rarity !== b.avatar.rarity) return b.avatar.rarity - a.avatar.rarity;
if (a.element !== b.element) return a.element.localeCompare(b.element); if (a.avatar.element !== b.avatar.element)
return a.avatar.element.localeCompare(b.avatar.element);
return a.cid - b.cid; return a.cid - b.cid;
}); });
roleList.value = roleData; roleList.value = roleData;
@@ -141,15 +102,12 @@ async function loadRole(): Promise<void> {
await TGLogger.Info( await TGLogger.Info(
`[Character][loadRole][${user.value.gameUid}] 共获取到${roleData.length}个角色`, `[Character][loadRole][${user.value.gameUid}] 共获取到${roleData.length}个角色`,
); );
} else {
await TGLogger.Warn(`[Character][loadRole][${user.value.gameUid}] 未获取到角色数据`);
}
} }
async function refreshRoles(): Promise<void> { async function refresh(): Promise<void> {
if (!user.value) return; if (!user.value) return;
await TGLogger.Info(`[Character][refreshRoles][${user.value.gameUid}] 正在更新角色数据`); await TGLogger.Info(`[Character][refreshRoles][${user.value.gameUid}] 正在更新角色数据`);
loadingTitle.value = "正在获取角色数据"; loadingTitle.value = "正在获取角色列表";
loading.value = true; loading.value = true;
if (!userStore.cookie.value) { if (!userStore.cookie.value) {
showSnackbar({ showSnackbar({
@@ -162,94 +120,48 @@ async function refreshRoles(): Promise<void> {
const cookie = { const cookie = {
account_id: userStore.cookie.value.account_id, account_id: userStore.cookie.value.account_id,
cookie_token: userStore.cookie.value.cookie_token, cookie_token: userStore.cookie.value.cookie_token,
ltoken: userStore.cookie.value.ltoken,
ltuid: userStore.cookie.value.ltuid,
}; };
const res = await TGRequest.User.byLToken.getRoleList(cookie, user.value); const listRes = await TGRequest.User.byCookie.getAvatarList(cookie, user.value.gameUid);
if (Array.isArray(res)) { if (!Array.isArray(listRes)) {
await TGLogger.Info(`[Character][refreshRoles][${user.value.gameUid}] 获取角色数据成功`); showSnackbar({
await TGLogger.Info( text: `[${listRes.retcode}] ${listRes.message}`,
`[Character][refreshRoles][${user.value.gameUid}] 共获取到${res.length}个角色`, color: "error",
});
await TGLogger.Error(`[Character][refreshRoles][${user.value.gameUid}] 获取角色列表失败`);
await TGLogger.Error(
`[Character][refreshRoles][${user.value.gameUid}] ${listRes.retcode} ${listRes.message}`,
); );
loadingTitle.value = "正在保存角色数据"; loading.value = false;
await TGSqlite.saveUserCharacter(user.value.gameUid, res); return;
loadingTitle.value = "正在更新角色数据"; }
await loadRole(); const idList = listRes.map((i) => i.id.toString());
} else { loadingTitle.value = "正在获取角色数据";
loadingSub.value = `${idList.length}个角色`;
const res = await TGRequest.User.byCookie.getAvatarDetail(cookie, user.value.gameUid, idList);
if ("retcode" in res) {
showSnackbar({ showSnackbar({
text: `[${res.retcode}] ${res.message}`, text: `[${res.retcode}] ${res.message}`,
color: "error", color: "error",
}); });
await TGLogger.Error(`[Character][refreshRoles][${user.value.gameUid}] 更新角色数据失败`); await TGLogger.Error(`[Character][refreshRoles][${user.value.gameUid}] 获取角色数据失败`);
await TGLogger.Error( await TGLogger.Error(
`[Character][refreshRoles][${user.value.gameUid}] ${res.retcode} ${res.message}`, `[Character][refreshRoles][${user.value.gameUid}] ${res.retcode} ${res.message}`,
); );
}
loading.value = false;
}
async function refreshTalent(): Promise<void> {
if (!user.value) return;
loadingTitle.value = "正在获取天赋数据";
loading.value = true;
if (!userStore.cookie.value) {
showSnackbar({
text: "请先登录",
color: "error",
});
loading.value = false; loading.value = false;
return; return;
} }
for (const role of roleList.value) { userStore.propMap.value = res.property_map;
loadingTitle.value = `正在获取${role.name}的天赋数据`; loadingTitle.value = "正在保存角色数据";
loadingSub.value = `CID${role.cid}`; await TSUserAvatar.saveAvatars(user.value.gameUid, res.list);
const res = await TGRequest.User.calculate.getSyncAvatarDetail( await TGLogger.Info(`[Character][refreshRoles][${user.value.gameUid}] 成功更新角色数据`);
userStore.cookie.value.account_id,
userStore.cookie.value.cookie_token,
user.value.gameUid,
role.cid,
);
if ("skill_list" in res) {
const talent: TGApp.Sqlite.Character.RoleTalent[] = [];
res.skill_list.map((skill, index) => {
return talent.push({
id: skill.id,
pos: index,
level: skill.level_current,
max: skill.max_level,
name: skill.name,
icon: skill.icon,
});
});
const skillStr = talent.map((i) => `${i.id}:${i.level}`).join(",");
await TGLogger.Info( await TGLogger.Info(
`[Character][refreshTalent][${user.value.gameUid}] 成功获取到${role.name}的天赋数据 ${skillStr}`, `[Character][refreshRoles][${user.value.gameUid}] 共更新${res.list.length}个角色`,
); );
await TGSqlite.saveUserCharacterTalent(user.value.gameUid, role.cid, talent); await load();
} else {
loadingTitle.value = `获取${role.name}的天赋数据失败`;
loadingSub.value = `[${res.retcode}] ${res.message}`;
await TGLogger.Error(
`[Character][refreshTalent][${user.value.gameUid}] 获取 ${role.name} 的天赋数据失败`,
);
await TGLogger.Error(
`[Character][refreshTalent][${user.value.gameUid}] ${res.retcode} ${res.message}`,
);
setTimeout(() => {}, 1000);
}
}
loadingTitle.value = "正在更新天赋数据";
loadingSub.value = "";
loading.value = false; loading.value = false;
showSnackbar({
text: "成功更新数据,即将刷新页面",
});
setTimeout(() => {
window.location.reload();
}, 1000);
} }
async function shareRoles(): Promise<void> { async function share(): Promise<void> {
if (!user.value) return; if (!user.value) return;
await TGLogger.Info(`[Character][shareRoles][${user.value.gameUid}] 正在生成分享图片`); await TGLogger.Info(`[Character][shareRoles][${user.value.gameUid}] 正在生成分享图片`);
const rolesBox = <HTMLElement>document.querySelector(".uc-box"); const rolesBox = <HTMLElement>document.querySelector(".uc-box");
@@ -323,6 +235,6 @@ function selectRole(role: TGApp.Sqlite.Character.UserRole): void {
.uc-grid { .uc-grid {
display: grid; display: grid;
grid-gap: 10px; grid-gap: 10px;
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); grid-template-columns: repeat(auto-fit, minmax(450px, 1fr));
} }
</style> </style>

View File

@@ -1,7 +1,7 @@
/** /**
* @file plugins/Sqlite/index.ts * @file plugins/Sqlite/index.ts
* @description Sqlite 数据库操作类 * @description Sqlite 数据库操作类
* @since Beta v0.5.0 * @since Beta v0.5.3
*/ */
import { app } from "@tauri-apps/api"; import { app } from "@tauri-apps/api";
@@ -14,7 +14,6 @@ import {
insertAppData, insertAppData,
insertGameAccountData, insertGameAccountData,
insertRecordData, insertRecordData,
insertRoleData,
} from "./sql/insertData.js"; } from "./sql/insertData.js";
class Sqlite { class Sqlite {
@@ -289,60 +288,6 @@ class Sqlite {
return res[0]; return res[0];
} }
/**
* @description 保存用户角色数据
* @since Beta v0.3.3
* @param {string} uid 用户 uid
* @param {TGApp.Game.Character.ListItem[]} data 角色数据
* @returns {Promise<void>}
*/
public async saveUserCharacter(
uid: string,
data: TGApp.Game.Character.ListItem[],
): Promise<void> {
const db = await this.getDB();
const sql = insertRoleData(uid, data);
await db.execute(sql);
}
/**
* @description 保存用户角色天赋数据
* @since Beta v0.3.3
* @param {string} uid 用户 uid
* @param {number} cid 角色 ID
* @param {TGApp.Sqlite.Character.RoleTalent[]} data 角色天赋数据
* @returns {Promise<void>}
*/
public async saveUserCharacterTalent(
uid: string,
cid: number,
data: TGApp.Sqlite.Character.RoleTalent[],
): Promise<void> {
const db = await this.getDB();
const sql = `UPDATE UserCharacters
SET talent = '${JSON.stringify(data)}',
updated = datetime('now', 'localtime')
WHERE uid = '${uid}'
AND cid = ${cid}`;
await db.execute(sql);
}
/**
* @description 获取用户角色数据
* @since Beta v0.3.3
* @param {string} uid 用户 uid
* @returns {Promise<TGApp.Sqlite.Character.UserRole[]|false>}
*/
public async getUserCharacter(uid: string): Promise<TGApp.Sqlite.Character.UserRole[] | false> {
const db = await this.getDB();
const sql = `SELECT *
FROM UserCharacters
WHERE uid = '${uid}'`;
const res: TGApp.Sqlite.Character.UserRole[] = await db.select(sql);
if (res.length === 0) return false;
return res;
}
/** /**
* @description 检测特定表是否存在 * @description 检测特定表是否存在
* @since Beta v0.4.5 * @since Beta v0.4.5

View File

@@ -5,6 +5,7 @@
*/ */
import TGSqlite from "../index.js"; import TGSqlite from "../index.js";
import { insertRoleData } from "../sql/insertData.js";
/** /**
* @description 获取用户角色id列表 * @description 获取用户角色id列表
@@ -18,8 +19,52 @@ async function getAllAvatarId(): Promise<string[]> {
return res.map((i) => i.cid); return res.map((i) => i.cid);
} }
/**
* @description 获取用户角色数据
* @since Beta v0.5.3
* @param {string} uid 用户 uid
* @returns {Promise<TGApp.Sqlite.Character.UserRole[]>}
*/
async function getAvatars(uid: string): Promise<TGApp.Sqlite.Character.UserRole[]> {
const db = await TGSqlite.getDB();
type resType = Array<TGApp.Sqlite.Character.UserRoleDB>;
const res = await db.select<resType>("SELECT * FROM UserCharacters WHERE uid = ?;", [uid]);
return res.map((i) => {
return {
uid: i.uid,
cid: i.cid,
avatar: JSON.parse(i.avatar),
weapon: JSON.parse(i.weapon),
relics: JSON.parse(i.relics),
constellations: JSON.parse(i.constellations),
costumes: JSON.parse(i.costumes),
skills: JSON.parse(i.skills),
propSelected: JSON.parse(i.propSelected),
propBase: JSON.parse(i.propBase),
propExtra: JSON.parse(i.propExtra),
propRecommend: JSON.parse(i.propRecommend),
updated: i.updated,
};
});
}
/**
* @description 保存用户角色数据
* @since Beta v0.5.3
* @param {string} uid 用户 uid
* @param {TGApp.Game.Avatar.DetailList[]} data 角色数据
* @returns {Promise<void>}
*/
async function saveAvatars(uid: string, data: TGApp.Game.Avatar.DetailList[]): Promise<void> {
const db = await TGSqlite.getDB();
const sql = insertRoleData(uid, data);
await db.execute(sql);
}
const TSUserAvatar = { const TSUserAvatar = {
getAllAvatarId, getAllAvatarId,
getAvatars,
saveAvatars,
}; };
export default TSUserAvatar; export default TSUserAvatar;

View File

@@ -1,6 +1,6 @@
-- @file plugins Sqlite sql createTable.sql -- @file plugins/Sqlite/sql/createTable.sql
-- @brief sqlite数据库创建表语句 -- @brief sqlite数据库创建表语句
-- @since Beta v0.4.5 -- @since Beta v0.5.3
-- @brief 创建成就数据表 -- @brief 创建成就数据表
create table if not exists Achievements create table if not exists Achievements
@@ -114,23 +114,24 @@ create table if not exists UserRecord
updated text updated text
); );
-- @brief 删除旧的角色数据表
drop table if exists UserCharacters;
-- @brief 创建角色数据表 -- @brief 创建角色数据表
create table if not exists UserCharacters create table if not exists UserCharacters
( (
uid integer, uid integer,
cid integer, cid integer,
img text, avatar text,
name text,
fetter integer,
level integer,
element text,
star integer,
weapon text, weapon text,
reliquary text, relics text,
constellation text, constellations text,
activeConstellation integer, costumes text,
costume text, skills text,
talent text, propSelected text,
propBase text,
propExtra text,
propRecommend text,
updated text, updated text,
primary key (uid, cid) primary key (uid, cid)
); );

View File

@@ -1,7 +1,7 @@
/** /**
* @file plugins Sqlite sql insertData.ts * @file plugins/Sqlite/sql/insertData.ts
* @description Sqlite 插入数据 sql 语句 * @description Sqlite 插入数据 sql 语句
* @since Beta v0.3.3 * @since Beta v0.5.3
*/ */
import { transCharacterData, transFloorData } from "../utils/transAbyssData.js"; import { transCharacterData, transFloorData } from "../utils/transAbyssData.js";
@@ -237,33 +237,31 @@ export function insertRecordData(data: TGApp.Game.Record.FullData, uid: string):
/** /**
* @description 插入用户角色数据 * @description 插入用户角色数据
* @since Alpha v0.2.1 * @since Beta v0.5.3
* @param {string} uid 用户 UID * @param {string} uid 用户 UID
* @param {TGApp.User.Character.Item[]} data 角色数据 * @param {TGApp.Game.Avatar.DetailList[]} data 角色数据
* @returns {string} sql * @returns {string} sql
*/ */
export function insertRoleData(uid: string, data: TGApp.Game.Character.ListItem[]): string { export function insertRoleData(uid: string, data: TGApp.Game.Avatar.DetailList[]): string {
const sql = data.map((item) => { const sql = data.map((item) => {
const role = transUserRoles(item); const role = transUserRoles(item);
return ` return `
INSERT INTO UserCharacters (uid, cid, name, img, name, fetter, level, element, star, weapon, reliquary, INSERT INTO UserCharacters (uid, cid, avatar, weapon, relics, constellations, costumes, skills,
constellation, activeConstellation, costume, updated) propSelected, propBase, propExtra, propRecommend, updated)
VALUES (${uid}, ${role.cid}, '${role.name}', '${role.img}', '${role.name}', ${role.fetter}, ${role.level}, VALUES (${uid}, ${role.cid}, '${role.avatar}', '${role.weapon}', '${role.relics}', '${role.constellations}',
'${role.element}', ${role.star}, '${role.weapon}', '${role.reliquary}', '${role.constellation}', '${role.costumes}', '${role.skills}', '${role.propSelected}', '${role.propBase}', '${role.propExtra}',
${role.activeConstellation}, '${role.costume}', datetime('now', 'localtime')) '${role.propRecommend}', datetime('now', 'localtime'))
ON CONFLICT(uid, cid) DO UPDATE ON CONFLICT(uid, cid) DO UPDATE
SET name = '${role.name}', SET avatar = '${role.avatar}',
img = '${role.img}',
name = '${role.name}',
fetter = ${role.fetter},
level = ${role.level},
element = '${role.element}',
star = ${role.star},
weapon = '${role.weapon}', weapon = '${role.weapon}',
reliquary = '${role.reliquary}', relics = '${role.relics}',
constellation = '${role.constellation}', constellations = '${role.constellations}',
activeConstellation = ${role.activeConstellation}, costumes = '${role.costumes}',
costume = '${role.costume}', skills = '${role.skills}',
propSelected = '${role.propSelected}',
propBase = '${role.propBase}',
propExtra = '${role.propExtra}',
propRecommend = '${role.propRecommend}',
updated = datetime('now', 'localtime'); updated = datetime('now', 'localtime');
`; `;
}); });

View File

@@ -1,157 +1,31 @@
/** /**
* @file plugins Sqlite utils transUserRoles.ts * @file plugins/Sqlite/utils/transUserRoles.ts
* @description 转换用户角色数据格式,用于数据库存储 * @description 转换用户角色数据格式,用于数据库存储
* @author BTMuli <bt-muli@outlook.com> * @since Beta v0.5.3
* @since Alpha v0.2.0
*/ */
enum EnumElementEn {
pyro = "Pyro",
hydro = "Hydro",
anemo = "Anemo",
electro = "Electro",
cryo = "Cryo",
geo = "Geo",
dendro = "Dendro",
}
enum EnumElement {
pyro = "火元素",
hydro = "水元素",
anemo = "风元素",
electro = "雷元素",
cryo = "冰元素",
geo = "岩元素",
dendro = "草元素",
}
/** /**
* @description 将通过 api 获取到的用户角色数据转换为数据库中的数据 * @description 将通过 api 获取到的用户角色数据转换为数据库中的数据
* @since Alpha v0.2.0 * @since Beta v0.5.3
* @param {TGApp.Game.Character.ListItem} data 用户角色数据 * @param {TGApp.Game.Character.ListItem} data 用户角色数据
* @returns {TGApp.Sqlite.Character.UserRole} 转换后的用户角色数据 * @returns {TGApp.Sqlite.Character.UserRole} 转换后的用户角色数据
*/ */
export function transUserRoles( export function transUserRoles(
data: TGApp.Game.Character.ListItem, data: TGApp.Game.Avatar.DetailList,
): TGApp.Sqlite.Character.UserRole { ): TGApp.Sqlite.Character.UserRoleDB {
return { return {
uid: -1, uid: -1,
cid: data.id, cid: data.base.id,
img: data.image, avatar: JSON.stringify(data.base),
name: data.name, weapon: JSON.stringify(data.weapon),
fetter: data.fetter, relics: JSON.stringify(data.relics),
level: data.level, constellations: JSON.stringify(data.constellations),
element: transElement(data.element), costumes: JSON.stringify(data.costumes),
star: data.rarity === 105 ? 5 : data.rarity, skills: JSON.stringify(data.skills),
weapon: transWeapon(data.weapon), propSelected: JSON.stringify(data.selected_properties),
reliquary: transReliquary(data.reliquaries), propBase: JSON.stringify(data.base_properties),
constellation: transConstellation(data.constellations), propExtra: JSON.stringify(data.extra_properties),
activeConstellation: data.actived_constellation_num, propRecommend: JSON.stringify(data.recommend_relic_property),
costume: JSON.stringify(data.costumes),
talent: "",
updated: "", updated: "",
}; };
} }
/**
* @description 将角色元素转换为数据库中的数据
* @since Alpha v0.2.0
* @param {EnumElementEn} data 角色元素
* @returns {EnumElement} 转换后的角色元素
*/
function transElement(data: EnumElementEn): EnumElement {
switch (data) {
case EnumElementEn.pyro:
return EnumElement.pyro;
case EnumElementEn.hydro:
return EnumElement.hydro;
case EnumElementEn.anemo:
return EnumElement.anemo;
case EnumElementEn.electro:
return EnumElement.electro;
case EnumElementEn.cryo:
return EnumElement.cryo;
case EnumElementEn.geo:
return EnumElement.geo;
case EnumElementEn.dendro:
return EnumElement.dendro;
default:
throw new Error("未知的角色元素类型");
}
}
/**
* @description 将角色武器转换为数据库中的数据
* @since Alpha v0.2.0
* @param {TGApp.Game.Character.LIWeapon} data 角色武器
* @returns {string} 转换后的角色武器
*/
function transWeapon(data: TGApp.Game.Character.LIWeapon): string {
const weapon: TGApp.Sqlite.Character.RoleWeapon = {
id: data.id,
name: data.name,
type: data.type_name,
star: data.rarity,
level: data.level,
promote: data.promote_level,
description: data.desc,
affix: data.affix_level,
};
return JSON.stringify(weapon);
}
/**
* @description 将角色命座转换为数据库中的数据
* @since Alpha v0.2.0
* @param {TGApp.Game.Character.LIRelic[]} data 角色命座
* @returns {string} 转换后的角色命座
*/
function transReliquary(data: TGApp.Game.Character.LIRelic[]): string {
if (data.length === 0) {
return "";
}
const reliquary: TGApp.Sqlite.Character.RoleReliquary[] = [];
for (const item of data) {
reliquary.push({
id: item.id,
name: item.name,
pos: item.pos,
posName: item.pos_name,
star: item.rarity,
level: item.level,
icon: item.icon,
set: {
id: item.set.id,
name: item.set.name,
effect: item.set.affixes.map((setItem) => {
return {
active: setItem.activation_number,
description: setItem.effect,
};
}),
},
});
}
return JSON.stringify(reliquary);
}
/**
* @description 将角色命座转换为数据库中的数据
* @since Alpha v0.2.0
* @param {TGApp.Game.Character.LIConstellation[]} data 角色命座
* @returns {string} 转换后的角色命座
*/
function transConstellation(data: TGApp.Game.Character.LIConstellation[]): string {
const constellation: TGApp.Sqlite.Character.RoleConstellation[] = [];
for (const item of data) {
constellation.push({
id: item.id,
name: item.name,
icon: item.icon,
description: item.effect,
active: item.is_actived,
pos: item.pos,
});
}
return JSON.stringify(constellation);
}

View File

@@ -123,12 +123,12 @@ declare namespace TGApp.Game.Avatar {
* @property {Relic[]} relics - 角色圣遗物信息 * @property {Relic[]} relics - 角色圣遗物信息
* @property {Constellation[]} constellations - 角色命座信息 * @property {Constellation[]} constellations - 角色命座信息
* @property {Costume[]} costumes - 角色时装信息 * @property {Costume[]} costumes - 角色时装信息
* @property {WeaponProp[]} selected_properties - 角色选中属性 * @property {Prop[]} selected_properties - 角色选中属性
* @property {WeaponProp[]} base_properties - 角色基础属性 * @property {Prop[]} base_properties - 角色基础属性
* @property {WeaponProp[]} extra_properties - 角色额外属性 * @property {Prop[]} extra_properties - 角色额外属性
* @property {WeaponProp[]} element_properties - 角色元素属性 * @property {Prop[]} element_properties - 角色元素属性
* @property {Skill[]} skills - 角色技能信息 * @property {Skill[]} skills - 角色技能信息
* @property {RelicRecommendProp[]} recommend_relic_properties - 推荐圣遗物属性 * @property {RelicRecommendProp} recommend_relic_property - 推荐圣遗物属性
* @return DetailList * @return DetailList
*/ */
interface DetailList { interface DetailList {
@@ -137,12 +137,12 @@ declare namespace TGApp.Game.Avatar {
relics: Relic[]; relics: Relic[];
constellations: Constellation[]; constellations: Constellation[];
costumes: Costume[]; costumes: Costume[];
selected_properties: WeaponProp[]; selected_properties: Prop[];
base_properties: WeaponProp[]; base_properties: Prop[];
extra_properties: WeaponProp[]; extra_properties: Prop[];
element_properties: WeaponProp[]; element_properties: Prop[];
skills: Skill[]; skills: Skill[];
recommend_relic_properties: RelicRecommendProp[]; recommend_relic_property: RelicRecommendProp;
} }
/** /**
@@ -159,8 +159,8 @@ declare namespace TGApp.Game.Avatar {
* @property {string} type_name - 武器类型名称 * @property {string} type_name - 武器类型名称
* @property {string} desc - 武器描述 * @property {string} desc - 武器描述
* @property {number} affix_level - 武器精炼等级 * @property {number} affix_level - 武器精炼等级
* @property {WeaponProp} main_property - 武器主属性 * @property {Prop} main_property - 武器主属性
* @property {WeaponProp} sub_property - 武器副属性 * @property {Prop} sub_property - 武器副属性
* @return WeaponDetail * @return WeaponDetail
*/ */
interface WeaponDetail { interface WeaponDetail {
@@ -174,21 +174,21 @@ declare namespace TGApp.Game.Avatar {
type_name: string; type_name: string;
desc: string; desc: string;
affix_level: number; affix_level: number;
main_property: WeaponProp; main_property: Prop;
sub_property: WeaponProp; sub_property: Prop;
} }
/** /**
* @description 角色详情武器属性数据类型 * @description 角色详情武器属性数据类型
* @interface WeaponProp * @interface Prop
* @since Beta v0.5.3 * @since Beta v0.5.3
* @property {number} property_type - 属性类型 * @property {number} property_type - 属性类型
* @property {string} base - 基础属性 * @property {string} base - 基础属性
* @property {string} add - 附加属性 * @property {string} add - 附加属性
* @property {string} final - 最终属性 * @property {string} final - 最终属性
* @return WeaponProp * @return Prop
*/ */
interface WeaponProp { interface Prop {
property_type: number; property_type: number;
base: string; base: string;
add: string; add: string;

View File

@@ -1,12 +1,12 @@
/** /**
* @file types/Sqlite/Character.d.ts * @file types/Sqlite/Character.d.ts
* @description 角色相关类型定义文件 * @description 角色相关类型定义文件
* @since Alpha v0.2.0 * @since Beta v0.5.3
*/ */
/** /**
* @namespace TGApp.Sqlite.Character * @namespace TGApp.Sqlite.Character
* @since Alpha v0.2.0 * @since Beta v0.5.3
* @description 角色相关类型定义命名空间 * @description 角色相关类型定义命名空间
* @memberof TGApp.Sqlite * @memberof TGApp.Sqlite
*/ */
@@ -40,157 +40,71 @@ declare namespace TGApp.Sqlite.Character {
/** /**
* @description 用户角色列表的角色类型 * @description 用户角色列表的角色类型
* @since Alpha v0.2.1 * @since Beta v0.5.3
* @interface UserRole * @interface UserRole
* @property {number} uid - 用户 ID * @property {number} uid - 用户 ID
* @property {number} cid - 角色 ID * @property {number} cid - 角色 ID
* @property {string} img - 全身像 * @property {TGApp.Game.Avatar.Avatar} avatar - 角色信息
* @property {string} name - 角色名称 * @property {TGApp.Game.Avatar.WeaponDetail} weapon - 角色武器信息
* @property {number} fetter - 角色好感 * @property {TGApp.Game.Avatar.Relic[]} relics - 角色圣遗物信息
* @property {number} level - 角色等级 * @property {TGApp.Game.Avatar.Constellation[]} constellations - 角色命之座信息
* @property {string} element - 角色元素类型 * @property {TGApp.Game.Avatar.Costume[]} costumes - 角色衣装信息
* @property {number} star - 角色星级 * @property {TGApp.Game.Avatar.Skill[]} skills - 角色技能信息
* @property {RoleWeapon} weapon - 角色武器类型 // 数据库中以字符串形式存储 * @property {TGApp.Game.Avatar.Prop[]} propSelected - 角色属性信息
* @property {RoleReliquary[]} reliquary - 角色圣遗物套装 // 数据库中以字符串形式存储 * @property {TGApp.Game.Avatar.Prop[]} propBase - 角色基础属性信息
* @property {RoleConstellation[]} constellation - 角色命座 // 数据库中以字符串形式存储 * @property {TGApp.Game.Avatar.Prop[]} propExtra - 角色额外属性信息
* @property {number} activeConstellation - 角色激活命座 * @property {TGApp.Game.Avatar.RelicRecommendProp} propRecommend - 角色推荐属性信息
* @property {RoleCostume} costume - 角色时装 // 数据库中以字符串形式存储
* @property {RoleTalent[]} talent - 角色天赋 // 数据库中以字符串形式存储
* @property {string} updated - 数据更新时间 * @property {string} updated - 数据更新时间
* @return UserRole * @return UserRole
*/ */
interface UserRole { interface UserRole {
uid: number; uid: number;
cid: number; cid: number;
img: string; avatar: TGApp.Game.Avatar.Avatar;
name: string; weapon: TGApp.Game.Avatar.WeaponDetail;
fetter: number; relics: TGApp.Game.Avatar.Relic[];
level: number; constellations: TGApp.Game.Avatar.Constellation[];
element: string; costumes: TGApp.Game.Avatar.Costume[];
star: number; skills: TGApp.Game.Avatar.Skill[];
weapon: string; propSelected: TGApp.Game.Avatar.Prop[];
reliquary: string; propBase: TGApp.Game.Avatar.Prop[];
constellation: string; propExtra: TGApp.Game.Avatar.Prop[];
activeConstellation: number; propRecommend: TGApp.Game.Avatar.RelicRecommendProp;
costume: string;
talent: string;
updated: string; updated: string;
} }
/** /**
* @description 角色列表的武器数据类型 * @description 存于数据库的角色数据
* @since Alpha v0.2.0 * @since Beta v0.5.3
* @interface RoleWeapon * @interface UserRoleDB
* @property {number} id - 武器 ID * @property {number} uid - 用户 ID
* @property {string} name - 武器名称 * @property {number} cid - 角色 ID
* @property {string} type - 武器类型 * @property {string} avatar - 角色信息
* @property {number} star - 武器星级 * @property {string} weapon - 角色武器信息
* @property {number} level - 武器等级 * @property {string} relics - 角色圣遗物信息
* @property {number} promote - 武器突破 * @property {string} constellations - 角色命之座信息
* @property {string} description - 武器描述 * @property {string} costumes - 角色衣装信息
* @property {number} affix - 武器精炼 * @property {string} skills - 角色技能信息
* @return RoleWeapon * @property {string} propSelected - 角色属性信息
* @property {string} propBase - 角色基础属性信息
* @property {string} propExtra - 角色额外属性信息
* @property {string} propRecommend - 角色推荐属性信息
* @property {string} updated - 数据更新时间
* @return UserRoleDB
*/ */
interface RoleWeapon { interface UserRoleDB {
id: number; uid: number;
name: string; cid: number;
type: string; avatar: string;
star: number; weapon: string;
level: number; relics: string;
promote: number; constellations: string;
description: string; costumes: string;
affix: number; skills: string;
} propSelected: string;
propBase: string;
/** propExtra: string;
* @description 角色列表的圣遗物数据类型 propRecommend: string;
* @since Alpha v0.2.0 updated: string;
* @interface RoleReliquary
* @property {number} id - 圣遗物 ID
* @property {string} name - 圣遗物名称
* @property {number} pos - 圣遗物部位
* @property {string} posName - 圣遗物部位名称
* @property {number} star - 圣遗物星级
* @property {number} level - 圣遗物等级
* @property {string} icon - 圣遗物图标
* @property {number} set.id - 圣遗物套装 ID
* @property {string} set.name - 圣遗物套装名称
* @property {number} set.effect[].active - 圣遗物套装效果激活数量
* @property {string} set.effect[].description - 圣遗物套装效果描述
* @return RoleReliquary
*/
interface RoleReliquary {
id: number;
name: string;
pos: number;
posName: string;
star: number;
level: number;
icon: string;
set: {
id: number;
name: string;
effect: Array<{
active: number;
description: string;
}>;
};
}
/**
* @description 角色列表的命座数据类型
* @since Alpha v0.2.0
* @interface RoleConstellation
* @property {number} id - 命座 ID
* @property {string} name - 命座名称
* @property {string} icon - 命座图标
* @property {string} description - 命座描述
* @property {boolean} active - 命座是否激活
* @property {number} pos - 命座位置
* @return RoleConstellation
*/
interface RoleConstellation {
id: number;
name: string;
icon: string;
description: string;
active: boolean;
pos: number;
}
/**
* @description 角色列表的时装数据类型
* @since Alpha v0.2.0
* @interface RoleCostume
* @property {number} id - 时装 ID
* @property {string} name - 时装名称
* @property {string} icon - 时装图标
* @return RoleCostume
*/
interface RoleCostume {
id: number;
name: string;
icon: string;
}
/**
* @description 角色列表的天赋数据类型
* @since Alpha v0.2.1
* @interface RoleTalent
* @property {number} id - 天赋 ID
* @property {number} pos - 天赋位置
* @property {string} name - 天赋名称
* @property {string} icon - 天赋图标
* @property {number} max - 天赋最大等级
* @property {number} level - 天赋等级
* @return RoleTalent
*/
interface RoleTalent {
id: number;
pos: number;
name: string;
icon: string;
max: number;
level: number;
} }
} }