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

im
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 // 3. WebSocket + 线pullOnce finally loading
webSocketStore.connect() webSocketStore.connect()
await pullOnce() 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. // 4.
const sorted = conversationStore.getSortedConversations 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 { useFaceStore } from '@/views/im/home/store/faceStore'
import { IM_EMOJI_LIST } from '@/views/im/utils/emoji' import { IM_EMOJI_LIST } from '@/views/im/utils/emoji'
import { probeImageSize } from '@/views/im/utils/image' 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' }) defineOptions({ name: 'ImFacePicker' })

View File

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

View File

@ -4,13 +4,15 @@ import { store } from '@/store'
import { import {
getFacePackList as apiGetFacePackList, getFacePackList as apiGetFacePackList,
type ImFacePackUserVO
} from '@/api/im/face/pack'
import {
getFaceUserItemList as apiGetFaceUserItemList, getFaceUserItemList as apiGetFaceUserItemList,
createFaceUserItem as apiCreateFaceUserItem, createFaceUserItem as apiCreateFaceUserItem,
deleteFaceUserItem as apiDeleteFaceUserItem, deleteFaceUserItem as apiDeleteFaceUserItem,
type ImFacePackUserVO,
type ImFaceUserItemVO, type ImFaceUserItemVO,
type ImFaceUserItemSaveReqVO type ImFaceUserItemSaveReqVO
} from '@/api/im/face' } from '@/api/im/face/useritem'
/** /**
* IM store + * IM store +

View File

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

View File

@ -108,7 +108,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import { dateFormatter } from '@/utils/formatTime' 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' }) defineOptions({ name: 'ImManagerFaceUserItem' })