💄 合成显示具有材料

This commit is contained in:
BTMuli
2025-12-20 00:36:41 +08:00
parent 7218b70da4
commit 6911d61025
7 changed files with 268 additions and 69 deletions

View File

@@ -0,0 +1,19 @@
/**
* 一些功能集合
* @since Beta v0.9.0
*/
@use "sass:map";
/** 根据传入星级返回颜色 */
@function get-od-star-color($star:0) {
$star-color-map: (
1:#abb2bfff,
2:#98c379ff,
3:#61afefff,
4:#c678ddff,
5:#d19a66ff
);
@if map.has-key($star-color-map, $star) {
@return map.get($star-color-map, $star);
}
@return #e06c75ff;
}

View File

@@ -63,6 +63,7 @@ $pb-mi-base: v-bind(idColor); /* stylelint-disable-line value-keyword-case */
display: flex;
overflow: hidden;
height: 48px;
box-sizing: border-box;
align-items: center;
justify-content: flex-start;
padding-right: 8px;

View File

@@ -0,0 +1,135 @@
<!-- 背包材料转换项材料单项 -->
<template>
<div
:class="[`star${props.material.star}`, `${props.material.local === 0 ? 'empty' : ''}`]"
:title="props.material.name"
class="pbo-cm-box"
>
<div class="pbo-cm-left">
<img :src="`/icon/bg/${props.material.star}-Star.webp`" alt="bg" class="bg" />
<img :src="`/icon/material/${props.material.id}.webp`" alt="icon" class="icon" />
</div>
<div class="pbo-cm-right">
<span class="pbo-cm-title">{{ props.material.name }}</span>
<span class="pbo-cm-count">x{{ props.material.count }}</span>
</div>
<div :title="`持有:${props.material.local}`" class="pbo-cm-local">
{{ props.material.local }}
</div>
<div class="pbo-cm-extra">{{ props.material.type }}·{{ props.material.id }}</div>
</div>
</template>
<script lang="ts" setup>
import { PboConvertSource } from "./pbo-convert.vue";
type PbMaterialItemProps = { material: PboConvertSource };
const props = defineProps<PbMaterialItemProps>();
</script>
<style lang="scss" scoped>
@use "@styles/utils.scss" as utils;
@use "@styles/github.styles.scss" as github-styles;
.pbo-cm-box {
position: relative;
display: flex;
overflow: hidden;
min-width: 200px;
height: 48px;
align-items: center;
justify-content: flex-start;
padding-right: 4px;
border-radius: 4px;
column-gap: 4px;
&.empty {
opacity: 0.4;
}
}
.pbo-cm-left {
position: relative;
height: 100%;
flex-shrink: 0;
aspect-ratio: 1;
.bg,
.icon {
position: absolute;
top: 0;
width: 100%;
height: 100%;
}
}
.pbo-cm-right {
position: relative;
display: flex;
overflow: hidden;
max-width: 100%;
align-items: flex-end;
justify-content: center;
color: var(--box-text-2);
column-gap: 8px;
text-overflow: ellipsis;
white-space: nowrap;
word-break: break-all;
}
.pbo-cm-title {
font-size: 14px;
}
.pbo-cm-count {
position: relative;
border-radius: 12px;
color: var(--tgc-od-red);
font-family: var(--font-title);
font-size: 12px;
}
.pbo-cm-extra {
position: absolute;
z-index: 1;
right: 2px;
bottom: 0;
font-size: 8px;
font-style: italic;
opacity: 0.8;
}
.pbo-cm-local {
position: absolute;
top: 0;
right: 0;
box-sizing: border-box;
padding-right: 4px;
padding-left: 12px;
border-top: unset;
border-right: unset;
border-bottom-left-radius: 12px;
font-family: var(--font-title);
font-size: 10px;
line-height: 12px;
text-align: center;
}
@for $i from 1 through 5 {
.star#{$i} {
$pbo-cm-base: utils.get-od-star-color($i);
border: 1px solid rgba($pbo-cm-base, 0.2);
background: rgba($pbo-cm-base, 0.15);
.pbo-cm-extra {
color: $pbo-cm-base;
}
.pbo-cm-local {
@include github-styles.github-tag-dark-gen($pbo-cm-base);
border-top: unset;
border-right: unset;
}
}
}
</style>

View File

@@ -0,0 +1,57 @@
<!-- 背包材料合成 -->
<template>
<div class="pboc-container">
<v-icon>mdi-all-inclusive</v-icon>
<PboConvertMaterial v-for="(material, index) in convertSources" :key="index" :material />
</div>
</template>
<script lang="ts" setup>
import TSUserBagMaterial from "@Sqlm/userBagMaterial.js";
import { shallowRef, watch } from "vue";
import PboConvertMaterial from "./pbo-convert-material.vue";
/** 组件参数 */
type PboConvertProps = {
/** 用户UID */
uid: number;
/** 转换材料 */
data: TGApp.App.Material.Convert;
};
/** 渲染数据 */
export type PboConvertSource = TGApp.App.Material.ConvertSrc & {
/** 本地数量 */
local: number;
};
const props = defineProps<PboConvertProps>();
const convertSources = shallowRef<Array<PboConvertSource>>([]);
watch(
() => props.data,
async () => await loadData(),
{ immediate: true },
);
async function loadData(): Promise<void> {
const tmp: Array<PboConvertSource> = [];
for (const item of props.data.source) {
let cnt: number = 0;
const dbGet = await TSUserBagMaterial.getMaterial(props.uid, item.id);
if (dbGet.length > 0) cnt = dbGet[0].count;
tmp.push({ ...item, local: cnt });
}
convertSources.value = tmp;
}
</script>
<style lang="css" scoped>
.pboc-container {
position: relative;
display: flex;
width: 100%;
align-items: center;
justify-content: flex-start;
border-radius: 4px;
column-gap: 8px;
}
</style>

View File

@@ -11,10 +11,9 @@
<div class="pbom-icon">
<img :src="`/icon/bg/${props.data.info.star}-BGC.webp`" alt="bg" class="bg" />
<img :src="`/icon/material/${props.data.info.id}.webp`" alt="icon" class="icon" />
<span class="cnt">{{ dbInfo.count }}</span>
</div>
<div class="pbom-name" @click="shareMaterial()">{{ props.data.info.name }}</div>
<div class="pbom-type">{{ props.data.info.type }}</div>
<div class="pbom-type">持有{{ dbInfo.count }}·{{ props.data.info.type }}</div>
</div>
<div class="pbom-mid">
<div class="pbom-desc" v-html="parseHtmlText(props.data.info.description)" />
@@ -22,10 +21,11 @@
<TwoSource v-for="(item, index) in props.data.info.source" :key="index" :data="item" />
</div>
<div v-if="props.data.info.convert.length > 0" class="pbom-convert">
<TwoConvert
<PboConvert
v-for="(item, index) in props.data.info.convert"
:key="index"
:data="item"
:uid="props.uid"
/>
</div>
</div>
@@ -53,7 +53,6 @@
import TOverlay from "@comp/app/t-overlay.vue";
import showDialog from "@comp/func/dialog.js";
import showSnackbar from "@comp/func/snackbar.js";
import TwoConvert from "@comp/pageWiki/two-convert.vue";
import TwoSource from "@comp/pageWiki/two-source.vue";
import TSUserBagMaterial from "@Sqlm/userBagMaterial.js";
import { getVersion } from "@tauri-apps/api/app";
@@ -61,9 +60,11 @@ import { generateShareImg } from "@utils/TGShare.js";
import { parseHtmlText, timestampToDate } from "@utils/toolFunc.js";
import { onMounted, ref, shallowRef, watch } from "vue";
import PboConvert from "./pbo-convert.vue";
import type { MaterialInfo } from "@/pages/common/PageBagMaterial.vue";
type PboMaterialProps = { data: MaterialInfo; uid: string };
type PboMaterialProps = { data: MaterialInfo; uid: number };
type PboMaterialEmits = (e: "updateDB", v: MaterialInfo) => void;
const props = defineProps<PboMaterialProps>();
@@ -141,7 +142,7 @@ async function tryEdit(): Promise<void> {
flex-direction: column;
padding: 10px;
border-radius: 10px;
background: var(--box-bg-1);
background: var(--app-page-bg);
overflow-y: auto;
row-gap: 10px;
}
@@ -193,20 +194,6 @@ async function tryEdit(): Promise<void> {
width: 56px;
height: 56px;
}
.cnt {
@include github-styles.github-tag-dark-gen(#ffcd0c);
position: absolute;
bottom: -4px;
left: 40px;
width: fit-content;
padding: 0 4px;
border-radius: 12px;
backdrop-filter: blur(5px);
font-size: 10px;
text-align: center;
}
}
.pbom-name {
@@ -234,8 +221,8 @@ async function tryEdit(): Promise<void> {
.pbom-convert {
padding: 8px;
border-radius: 4px;
background: var(--box-bg-2);
color: var(--box-text-2);
background: var(--box-bg-1);
color: var(--box-text-1);
}
.pbom-desc {
@@ -268,7 +255,7 @@ async function tryEdit(): Promise<void> {
justify-content: flex-start;
padding: 8px;
border-radius: 4px;
background: var(--box-bg-2);
background: var(--box-bg-1);
row-gap: 8px;
}

View File

@@ -84,7 +84,7 @@
v-if="curMaterial"
v-model="showOverlay"
:data="curMaterial"
:uid="`${curUid}`"
:uid="curUid"
@updateDB="handleUpdate"
>
<template #left>

View File

@@ -1,68 +1,68 @@
/**
* @file types/App/Material.d.ts
* @description 应用素材日历相关类型定义文件
* @since Beta v0.4.2
* 应用素材日历相关类型定义文件
* @since Beta v0.9.0
*/
declare namespace TGApp.App.Material {
/**
* @description wiki 页的信息
* WIKI信息
* @since Beta v0.4.2
* @interface WikiItem
* @property {number} id - 材料id
* @property {string} name - 材料名称
* @property {string} description - 材料简介
* @property {string} type - 材料类型
* @property {number} star - 材料星级
* @property {Source[]} source - 材料来源
* @property {Convert[]} convert - 材料转换
* @return WikiItem
*/
interface WikiItem {
type WikiItem = {
/** 材料ID */
id: number;
/** 材料名称 */
name: string;
/** 材料简介 */
description: string;
/** 材料类型 */
type: string;
/** 材料星级 */
star: number;
source: Source[];
convert: Convert[];
}
/** 材料来源 */
source: Array<Source>;
/** 材料转换 */
convert: Array<Convert>;
};
/**
* @description 材料来源
* 材料来源
* @since Beta v0.4.4
* @interface Source
* @property {string} name - 来源名称
* @property {string} type - 来源类型
* @property {number[]} days - 来源日
* @return Source
*/
interface Source {
type Source = {
/** 来源名称 */
name: string;
/** 来源类型 */
type: string;
days?: number[];
}
/** 掉落日期 */
days?: Array<number>;
};
/**
* @description 材料转换
* @since Beta v0.4.2
* @interface Convert
* @property {string} id 转换ID
* @property {string} souce[].id 转换前材料ID
* @property {string} souce[].name 转换前材料名称
* @property {string} source[].type 转换前材料类型
* @property {number} source[].star 转换前材料星级
* @property {number} souce[].count 转换前材料数量
* @return Convert
* 材料转换
* @since Beta v0.9.0
*/
interface Convert {
type Convert = {
/** 合成ID */
id: string;
source: Array<{
id: string;
name: string;
type: string;
star: number;
count: number;
}>;
}
/** 合成材料 */
source: Array<ConvertSrc>;
};
/**
* 转换来源
* @since Beta v0.9.0
*/
type ConvertSrc = {
/** 材料ID */
id: number;
/** 材料名称 */
name: string;
/** 材料类型 */
type: string;
/** 材料星级 */
star: number;
/** 需要数量 */
count: number;
};
}