支持动态头像

This commit is contained in:
BTMuli
2025-07-14 16:12:05 +08:00
parent cbf4e15809
commit f5b44c2e8a
6 changed files with 144 additions and 27 deletions

View File

@@ -2,7 +2,7 @@
<div class="tp-avatar-box">
<div class="tpa-img">
<div class="tpa-icon">
<TMiImg :ori="true" :src="props.data.avatar_url" alt="avatar" />
<TMiImg :ori="true" :src="getUserAvatar(props.data)" alt="avatar" />
</div>
<div v-if="props.data.pendant !== ''" class="tpa-pendant">
<TMiImg :ori="true" :src="props.data.pendant" alt="pendant" />
@@ -25,6 +25,7 @@
</template>
<script lang="ts" setup>
import TMiImg from "@comp/app/t-mi-img.vue";
import { getUserAvatar } from "@utils/toolFunc.js";
import { computed } from "vue";
type TpAvatarProps = { data: TGApp.BBS.Post.User; position: "left" | "right" };

View File

@@ -5,7 +5,7 @@
<div class="vp-ouu-info">
<div class="left">
<div class="avatar">
<TMiImg :src="userInfo.avatar_url" alt="avatar" :ori="true" />
<TMiImg :src="getUserAvatar(userInfo)" alt="avatar" :ori="true" />
</div>
<div class="pendant" v-if="userInfo.pendant !== ''">
<TMiImg :src="userInfo.pendant" alt="pendant" :ori="true" />
@@ -46,6 +46,7 @@ import showSnackbar from "@comp/func/snackbar.js";
import { useBoxReachBottom } from "@hooks/reachBottom.js";
import bbsReq from "@req/bbsReq.js";
import postReq from "@req/postReq.js";
import { getUserAvatar } from "@utils/toolFunc.js";
import { computed, ref, shallowRef, useTemplateRef, watch } from "vue";
type ToPostUserProps = { gid: number; uid: string; postId?: string };

View File

@@ -10,7 +10,7 @@
<div class="tpr-user" @click="handleUser()">
<div class="tpru-left">
<div class="avatar">
<TMiImg :ori="true" :src="props.modelValue.user.avatar_url" alt="avatar" />
<TMiImg :ori="true" :src="getUserAvatar(props.modelValue.user)" alt="avatar" />
</div>
<div class="pendant" v-if="props.modelValue.user.pendant !== ''">
<TMiImg :ori="true" :src="props.modelValue.user.pendant" alt="pendant" />
@@ -109,7 +109,7 @@ import { emit, type Event, type UnlistenFn } from "@tauri-apps/api/event";
import { save } from "@tauri-apps/plugin-dialog";
import { writeTextFile } from "@tauri-apps/plugin-fs";
import { generateShareImg } from "@utils/TGShare.js";
import { getNearTime, timestampToDate } from "@utils/toolFunc.js";
import { getNearTime, getUserAvatar, timestampToDate } from "@utils/toolFunc.js";
import { computed, onMounted, onUnmounted, ref, shallowRef, toRaw, watch } from "vue";
import TpParser from "./tp-parser.vue";

27
src/enum/bbs.ts Normal file
View File

@@ -0,0 +1,27 @@
/**
* @file src/enum/bbs.ts
* @description BBS 相关枚举
* @since Beta v0.7.9
*/
/**
* @description 用户头像类型
* @since Beta v0.7.9
* @enum AvatarExtTypeEnum
*/
export const AvatarExtTypeEnum: typeof TGApp.BBS.User.AvatarExtType = {
CUSTOM: 0,
GIF: 3,
};
/**
* @description 头像拓展资源类型
* @since Beta v0.7.9
* @enum AvatarExtResTypeEnum
*/
export const AvatarExtResTypeEnum: typeof TGApp.BBS.User.AvatarExtResType = {
WEBP: 1,
APNG: 2,
GIF: 3,
PNG: 4,
};

View File

@@ -1,7 +1,7 @@
/**
* @file types/BBS/User.d.ts
* @description 用户类型定义文件
* @since Beta v0.7.2
* @since Beta v0.7.9
*/
declare namespace TGApp.BBS.User {
@@ -58,7 +58,7 @@ declare namespace TGApp.BBS.User {
/**
* @description 主页用户信息-二级
* @since Beta v0.7.2
* @since Beta v0.7.9
* @interface Info
* @property {string} uid 用户 ID
* @property {string} nickname 用户昵称
@@ -67,7 +67,7 @@ declare namespace TGApp.BBS.User {
* @property {number} gender 用户性别
* @property {Certification} certification 用户认证信息
* @property {LevelExp[]} level_exps 用户等级经验
* @property {Archive} archive 用户档案
* @property {Achieve} archive 用户档案
* @property {Community} community_info 用户社区信息
* @property {string} avatar_url 用户头像链接
* @property {Certification[]} certifications 用户认证信息
@@ -75,7 +75,8 @@ declare namespace TGApp.BBS.User {
* @property {string} pendant 用户挂件 URL可能为 ""
* @property {boolean} is_logoff 是否注销
* @property {string} ip_region 用户 IP 地区
* @return Info
* @property {string | null} showText 显示文本,可能为 null
* @property {AvatarExt} avatar_ext 用户头像扩展信息
*/
type Info = {
uid: string;
@@ -85,7 +86,7 @@ declare namespace TGApp.BBS.User {
gender: number;
certification: Certification;
level_exps: Array<LevelExp>;
archive: Archive;
archive: Achieve;
community_info: Community;
avatar_url: string;
certifications: Array<Certification>;
@@ -93,6 +94,8 @@ declare namespace TGApp.BBS.User {
pendant: string;
is_logoff: boolean;
ip_region: string;
showText: string | null; // 显示文本,可能为 null
avatar_ext: AvatarExt;
};
/**
@@ -128,26 +131,80 @@ declare namespace TGApp.BBS.User {
type SelfOperation = { attitude: number; is_collected: boolean; upvote_type: number };
/**
* @description 用户头像扩展信息
* @since Beta v0.7.2
* @interface AvatarExt
* @property {number} avatar_type 头像类型
* @property {string} avatar_assets_id 头像资源 ID
* @property {Array<unknown>} resources 资源
* @property {Array<unknown>} hd_resources 高清资源
* @return AvatarExt
* @description 用户头像类型
* @since Beta v0.7.9
* @const AvatarExtType
* @enum {number}
* @property {number} CUSTOM - 自定义头像(0)
* @property {number} GIF - 可选动态头像(3)
*/
type AvatarExt = {
avatar_type: number;
avatar_assets_id: string;
resources: Array<unknown>;
hd_resources: Array<unknown>;
const AvatarExtType = <const>{
CUSTOM: 0,
GIF: 3,
};
/**
* @description 用户头像类型枚举
* @since Beta v0.7.9
* @enum {number}
* @type AvatarExtTypeEnum
*/
type AvatarExtTypeEnum = (typeof AvatarExtType)[keyof typeof AvatarExtType];
/**
* @description 用户头像扩展信息
* @since Beta v0.7.9
* @interface AvatarExt
* @property {AvatarExtTypeEnum} avatar_type 头像类型
* @property {string} avatar_assets_id 头像资源 ID
* @property {Array<AvatarExtRes>} resources 资源
* @property {Array<AvatarExtRes>} hd_resources 高清资源
* @return AvatarExt
*/
type AvatarExt = {
avatar_type: AvatarExtTypeEnum;
avatar_assets_id: string;
resources: Array<AvatarExtRes>;
hd_resources: Array<AvatarExtRes>;
};
/**
* @description 用户头像拓展资源类型
* @since Beta v0.7.9
* @const AvatarExtResType
* @property {number} WEBP - WEBP 格式
* @property {number} APNG - APNG 格式
* @property {number} GIF - GIF 格式
* @property {number} PNG - PNG 格式
*/
const AvatarExtResType = <const>{
WEBP: 1,
APNG: 2,
GIF: 3,
PNG: 4,
};
/**
* @description 用户头像拓展资源类型枚举
* @since Beta v0.7.9
* @enum {number}
* @type AvatarExtResTypeEnum
*/
type AvatarExtResTypeEnum = (typeof AvatarExtResType)[keyof typeof AvatarExtResType];
/**
* @description 用户头像拓展资源
* @since Beta v0.7.9
* @interface AvatarExtRes
* @property {AvatarExtResTypeEnum} format 资源格式
* @property {string} url 资源链接
*/
type AvatarExtRes = { format: AvatarExtResTypeEnum; url: string };
/**
* @description 用户档案
* @since Alpha v0.2.1
* @interface Archive
* @since Beta v0.7.9
* @interface Achieve
* @property {string} like_num 获赞数
* @property {string} post_num 发帖数
* @property {string} replypost_num 回帖数
@@ -157,9 +214,9 @@ declare namespace TGApp.BBS.User {
* @property {string} new_follower_num 新粉丝数
* @property {string} good_post_num 精华帖数
* @property {string} follow_collection_cnt 收藏数
* @return Archive
* @return Achieve
*/
type Archive = {
type Achieve = {
like_num: string;
post_num: string;
replypost_num: string;

View File

@@ -1,9 +1,10 @@
/**
* @file utils/toolFunc.ts
* @description 一些工具函数
* @since Beta v0.7.2
* @since Beta v0.7.9
*/
import { AvatarExtResTypeEnum, AvatarExtTypeEnum } from "@enum/bbs.js";
import { path } from "@tauri-apps/api";
import { type } from "@tauri-apps/plugin-os";
import colorConvert from "color-convert";
@@ -315,3 +316,33 @@ export function getWikiBrief(
}
return AppCharacterData.find((item) => item.id.toString() === id.toString()) ?? false;
}
/**
* @description 根据传入角色信息获取头像
* @since Beta v0.7.9
* @param {TGApp.BBS.Reply.User|TGApp.BBS.Post.User} user - 用户信息
* @returns {string} 头像链接
*/
export function getUserAvatar(
user: TGApp.BBS.Reply.User | TGApp.BBS.Post.User | TGApp.BBS.User.Info,
): string {
if (!user.avatar_ext) return user.avatar_url;
if (user.avatar_ext.avatar_type === AvatarExtTypeEnum.CUSTOM) return user.avatar_url;
if (user.avatar_ext.avatar_type === AvatarExtTypeEnum.GIF) {
const findGH = user.avatar_ext.hd_resources.find((i) => i.format === AvatarExtResTypeEnum.GIF);
if (findGH) return findGH.url;
const findG = user.avatar_ext.resources.find((i) => i.format === AvatarExtResTypeEnum.GIF);
if (findG) return findG.url;
const findWH = user.avatar_ext.hd_resources.find((i) => i.format === AvatarExtResTypeEnum.WEBP);
if (findWH) return findWH.url;
const findW = user.avatar_ext.resources.find((i) => i.format === AvatarExtResTypeEnum.WEBP);
if (findW) return findW.url;
const findPH = user.avatar_ext.hd_resources.find((i) => i.format === AvatarExtResTypeEnum.PNG);
if (findPH) return findPH.url;
const findP = user.avatar_ext.resources.find((i) => i.format === AvatarExtResTypeEnum.PNG);
if (findP) return findP.url;
return user.avatar_url;
}
// TODO: 处理其他类型头像
return user.avatar_url;
}