✨ feat(im): 初始化群申请 v0.3:第四把 review(优化界面,进一步对齐微信界面)【之前提交错了】

pull/881/head
YunaiV 2026-05-06 23:57:54 +08:00
parent f746aebe08
commit b2ba42049b
7 changed files with 32 additions and 29 deletions

View File

@ -1,3 +0,0 @@
// 用户端 IM 表情 API barrel 出口;按子目录(pack / userItem)二次拆分,调用方可用 `from '@/api/im/face'` 一次拿全
export * from './pack'
export * from './userItem'

View File

@ -96,14 +96,6 @@ onMounted(async () => {
// 3. 实时通信:建 WebSocket 长连接 + 拉离线消息(pullOnce finally 把 loading 归位)
webSocketStore.connect()
await pullOnce()
// 3.1 我管理的群下未处理加群申请,给顶部横幅 / Drawer 派生 count 与 list;失败不阻断主流程
// TODO @AI:可以挪到 1.2 那么?不阻塞就行呀。
void groupRequestStore.fetchUnhandledList().catch((e) =>
console.warn('[IM] 拉取未处理加群申请失败', e)
)
// 3.2 系统表情包后台预拉,消除表情面板首次展开的白屏;个人表情保持「点开 tab 才拉」
// TODO @AI:同上;
void faceStore.ensureFacePacks().catch((e) => console.warn('[IM] 后台预拉表情包失败', e))
// 4. 默认选中第一个会话;若置顶分组处于折叠态,需跳过被折叠隐藏的置顶项,避免自动展开折叠
const sorted = conversationStore.getSortedConversations

View File

@ -183,7 +183,8 @@ import { updateFile } from '@/api/infra/file'
import { useFaceStore } from '@/views/im/home/store/faceStore'
import { IM_EMOJI_LIST } from '@/views/im/utils/emoji'
import { probeImageSize } from '@/views/im/utils/image'
import type { ImFacePackUserItemVO, ImFaceUserItemVO } from '@/api/im/face'
import type { ImFacePackUserItemVO } from '@/api/im/face/pack'
import type { ImFaceUserItemVO } from '@/api/im/face/useritem'
defineOptions({ name: 'ImFacePicker' })

View File

@ -496,9 +496,20 @@ const videoPayload = computed(() =>
const cardPayload = computed(() =>
isCard.value ? parseMessage<CardMessage>(props.message.content) : null
)
const facePayload = computed(() =>
isFace.value ? parseMessage<FaceMessage>(props.message.content) : null
)
/** 表情 payload;非法宽高(缺失 / 0 / 负数 / 超出 2048)派生成 undefined,让 <img> 走 CSS max-w / max-h 兜底 */
const FACE_DIMENSION_MAX = 2048
const facePayload = computed(() => {
if (!isFace.value) {
return null
}
const raw = parseMessage<FaceMessage>(props.message.content)
if (!raw) {
return null
}
const sanitize = (v: number | undefined) =>
v && v > 0 && v <= FACE_DIMENSION_MAX ? v : undefined
return { ...raw, width: sanitize(raw.width), height: sanitize(raw.height) }
})
/** 名片点击:弹被推荐用户的 UserInfoCard;陌生人名片走「名片」加好友来源 */
function handleCardClick(e: MouseEvent) {

View File

@ -4,13 +4,15 @@ import { store } from '@/store'
import {
getFacePackList as apiGetFacePackList,
type ImFacePackUserVO
} from '@/api/im/face/pack'
import {
getFaceUserItemList as apiGetFaceUserItemList,
createFaceUserItem as apiCreateFaceUserItem,
deleteFaceUserItem as apiDeleteFaceUserItem,
type ImFacePackUserVO,
type ImFaceUserItemVO,
type ImFaceUserItemSaveReqVO
} from '@/api/im/face'
} from '@/api/im/face/useritem'
/**
* IM 表情面板数据 store(系统表情包 + 个人表情)

View File

@ -22,21 +22,21 @@
<el-form-item label="尺寸">
<el-input-number
v-model="formData.width"
:min="0"
:max="9999"
:min="1"
:max="2048"
controls-position="right"
class="!w-1/3"
/>
<span class="mx-2 text-[var(--el-text-color-secondary)]">×</span>
<el-input-number
v-model="formData.height"
:min="0"
:max="9999"
:min="1"
:max="2048"
controls-position="right"
class="!w-1/3"
/>
<span class="ml-2 text-12px text-[var(--el-text-color-placeholder)]">
上传后自动探测;可手动调整
上传后自动探测;可手动调整(1 ~ 2048 像素)
</span>
</el-form-item>
<el-form-item label="排序" prop="sort">
@ -92,8 +92,8 @@ const formData = ref({
packId: 0,
url: '',
name: '',
width: 0,
height: 0,
width: undefined as number | undefined,
height: undefined as number | undefined,
sort: 0,
status: CommonStatusEnum.ENABLE
})
@ -106,8 +106,8 @@ const formRef = ref() // 表单 Ref
/** 上传完成后从 URL 回探宽高,自动填表单(用户仍可手改) */
async function onUrlChange(url: string) {
if (!url) {
formData.value.width = 0
formData.value.height = 0
formData.value.width = undefined
formData.value.height = undefined
return
}
const size = await probeImageSize(url)
@ -165,8 +165,8 @@ const resetForm = () => {
packId: props.packId,
url: '',
name: '',
width: 0,
height: 0,
width: undefined,
height: undefined,
sort: 0,
status: CommonStatusEnum.ENABLE
}

View File

@ -108,7 +108,7 @@
<script lang="ts" setup>
import { dateFormatter } from '@/utils/formatTime'
import * as ManagerFaceUserItemApi from '@/api/im/manager/face/userItem'
import * as ManagerFaceUserItemApi from '@/api/im/manager/face/useritem'
defineOptions({ name: 'ImManagerFaceUserItem' })