️ 添加名片类型,描述智能换行

This commit is contained in:
BTMuli
2023-12-26 23:58:53 +08:00
parent 8fc8ace1eb
commit 6e5b3016f1
2 changed files with 150 additions and 3 deletions

View File

@@ -7,16 +7,17 @@
<img alt="bg" class="ton-bg" v-if="props.data" :src="props.data.profile" />
<div class="ton-content">
<span>{{ props.data.name }}</span>
<span>{{ props.data.desc }}</span>
<span>{{ parseNamecard(props.data.desc) }}</span>
<span>获取途径{{ props.data.source }}</span>
</div>
<div class="ton-type">{{ getType.text }}</div>
</div>
<slot name="right"></slot>
</div>
</TOverlay>
</template>
<script setup lang="ts">
import { computed } from "vue";
import { computed, watch } from "vue";
import TOverlay from "../main/t-overlay.vue";
@@ -25,12 +26,89 @@ interface ToNamecardProps {
data?: TGApp.App.NameCard.Item;
}
interface ToNamecardType {
text: string;
color: string;
background: string;
}
enum ToNamecardTypeEnum {
other = 0,
achievement = 1,
role = 2,
record = 3,
activity = 4,
unknown = 5,
}
type ToNamecardTypeMap = {
[key in ToNamecardTypeEnum]: ToNamecardType;
};
const typeMap: ToNamecardTypeMap = {
[ToNamecardTypeEnum.other]: {
text: "其他",
color: "var(--tgc-white-1)",
background: "var(--tgc-black-1)",
},
[ToNamecardTypeEnum.achievement]: {
text: "成就",
color: "var(--tgc-white-1)",
background: "var(--tgc-black-1)",
},
[ToNamecardTypeEnum.role]: {
text: "角色名片",
color: "var(--tgc-white-1)",
background: "var(--tgc-black-1)",
},
[ToNamecardTypeEnum.record]: {
text: "纪行名片",
color: "var(--tgc-white-1)",
background: "var(--tgc-black-1)",
},
[ToNamecardTypeEnum.activity]: {
text: "活动名片",
color: "var(--tgc-white-1)",
background: "var(--tgc-black-1)",
},
[ToNamecardTypeEnum.unknown]: {
text: "未知名片",
color: "var(--tgc-white-1)",
background: "var(--tgc-black-1)",
},
};
type ToNamecardEmits = (e: "update:modelValue", value: boolean) => void;
const props = defineProps<ToNamecardProps>();
const emits = defineEmits<ToNamecardEmits>();
watch(
() => props.data,
() => {
if (props.data) {
console.log(JSON.stringify(props.data.desc));
}
},
);
const getType = computed(() => {
if (!props.data) return typeMap[ToNamecardTypeEnum.unknown];
switch (props.data.type) {
case ToNamecardTypeEnum.achievement:
return typeMap[ToNamecardTypeEnum.achievement];
case ToNamecardTypeEnum.role:
return typeMap[ToNamecardTypeEnum.role];
case ToNamecardTypeEnum.record:
return typeMap[ToNamecardTypeEnum.record];
case ToNamecardTypeEnum.activity:
return typeMap[ToNamecardTypeEnum.activity];
default:
return typeMap[ToNamecardTypeEnum.other];
}
});
const visible = computed({
get: () => props.modelValue,
set: (value) => {
@@ -41,6 +119,61 @@ const visible = computed({
function onCancel() {
visible.value = false;
}
function parseNamecard(desc: string): string {
let array = [];
if (desc.startsWith("名片纹饰。「")) {
array.push("名片纹饰。");
const reg = /「.+?」/g;
const match = desc.match(reg);
if (match !== null) {
for (const item of match) {
if (item.length <= 34) {
array.push(item);
} else {
array.push("「");
array.push(...parseDesc(item.slice(1, -1)));
array.push("」");
}
}
}
} else {
array.push("名片纹饰。");
const content = desc.slice(5);
if (content.length <= 32) {
array.push(content);
} else {
array.push(...parseDesc(content));
}
}
const res = array.join("\n");
if (!res.endsWith("\n")) return res + "\n";
return res;
}
function parseDesc(desc: string): string[] {
let res = desc.replace(/。/g, "。\n");
res = res.replace(//g, "\n");
res = res.replace(//g, "\n");
res = res.replace(//g, "\n");
if (!desc.includes("!」")) {
res = res.replace(//g, "\n");
}
res = res.replace(/…/g, "…\n");
const match = res.split("\n");
const array: string[] = [];
for (const item of match) {
if (item.length > 0 && item.length <= 32) {
array.push(item);
} else {
const match2 = item.replace(//g, "\n").split("\n");
for (const item2 of match2) {
if (item2.length > 0) array.push(item2);
}
}
}
return array;
}
</script>
<style lang="css" scoped>
.ton-container {
@@ -56,6 +189,7 @@ function onCancel() {
width: 800px;
height: 400px;
border-radius: 10px;
box-shadow: 0 0 5px var(--common-shadow-2);
}
.ton-bg {
@@ -64,6 +198,18 @@ function onCancel() {
height: 100%;
}
.ton-type {
position: absolute;
top: 10px;
left: 10px;
padding: 0 5px;
border: 1px solid var(--tgc-white-1);
border-radius: 5px;
backdrop-filter: blur(5px);
color: var(--tgc-white-1);
text-shadow: 0 0 5px rgb(0 0 0/80%);
}
.ton-content {
position: absolute;
right: 0;
@@ -76,7 +222,6 @@ function onCancel() {
justify-content: flex-end;
padding: 10px;
background: rgb(0 0 0 / 20%);
box-shadow: 0 0 10px rgb(255 255 255 /20%);
color: var(--tgc-white-1);
text-shadow: 0 0 5px rgb(0 0 0/80%);
}
@@ -88,6 +233,7 @@ function onCancel() {
.ton-content :nth-child(2) {
opacity: 0.8;
white-space: pre-wrap;
}
.ton-content :nth-child(3) {

View File

@@ -1,5 +1,6 @@
<template>
<div class="tw-nc-box">
<!-- todo search -->
<v-virtual-scroll :items="AppNameCardsData" :item-height="80" class="cards-list">
<template #default="{ item }">
<v-list