IM聊天功能优化

This commit is contained in:
geht
2026-05-28 17:08:34 +08:00
parent 3539eab924
commit a63cd6ad1a
29 changed files with 3565 additions and 203 deletions

View File

@@ -0,0 +1,442 @@
<template>
<div class="im-biz-record-message">
<div v-if="showNoPermission" class="im-biz-record-no-permission">暂无当前消息权限</div>
<template v-else>
<template v-if="isSingleItem">
<div class="im-biz-record-item">
<div class="im-biz-record-table-wrap">
<table class="im-biz-record-table im-biz-record-table--detail">
<tbody>
<tr v-for="field in resolveItemFields(singleItem)" :key="field.label">
<th>{{ field.label }}</th>
<td>{{ field.value }}</td>
</tr>
</tbody>
</table>
</div>
<a class="im-biz-record-link" @click.prevent="handleLinkClick(singleItem.linkPath)">
<Icon icon="ant-design:link-outlined" />
<span>查看并定位到此数据</span>
</a>
</div>
</template>
<!-- 多条列表表第一列为定位链接 -->
<template v-else>
<div class="im-biz-record-table-wrap im-biz-record-table-wrap--list">
<table class="im-biz-record-table im-biz-record-table--list">
<thead>
<tr>
<th class="im-biz-record-link-col">链接</th>
<th v-for="columnLabel in listColumnLabels" :key="columnLabel">{{ columnLabel }}</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in payload.items" :key="item.recordId || index">
<td class="im-biz-record-link-col">
<a class="im-biz-record-link" @click.prevent="handleLinkClick(item.linkPath)">
<Icon icon="ant-design:link-outlined" />
<span>定位</span>
</a>
</td>
<td v-for="columnLabel in listColumnLabels" :key="columnLabel">
{{ getFieldValue(item, columnLabel) }}
</td>
</tr>
</tbody>
</table>
</div>
</template>
<div v-if="showPeerNoPermissionTip" class="im-biz-record-peer-tip">对方无此功能权限</div>
</template>
</div>
</template>
<script lang="ts" setup>
import { computed } from 'vue';
import type { ImBizRecordItem, ImBizRecordPayload } from './imBizRecordMessage';
import {
getImBizRecordFieldValueByLabel,
resolveImBizRecordItemFields,
resolveImBizRecordListColumnLabels,
} from './imBizRecordMessage';
import { navigateImBizRecordLink } from './imRecordLocate';
import { hasImBizRecordPagePermission } from './imBizRecordPermission';
defineOptions({ name: 'ImBizRecordMessageContent' });
const props = defineProps<{
payload: ImBizRecordPayload;
mine?: boolean;
receiverHasBizPagePermission?: boolean;
}>();
const isSingleItem = computed(() => props.payload.items.length === 1);
const singleItem = computed(() => props.payload.items[0]);
const listColumnLabels = computed(() => resolveImBizRecordListColumnLabels(props.payload.items));
const hasPagePermission = computed(() => hasImBizRecordPagePermission(props.payload.pagePath));
const showNoPermission = computed(() => !props.mine && !hasPagePermission.value);
const showPeerNoPermissionTip = computed(
() => !!props.mine && props.receiverHasBizPagePermission === false,
);
function resolveItemFields(item: ImBizRecordItem) {
return resolveImBizRecordItemFields(item);
}
function getFieldValue(item: ImBizRecordItem, label: string) {
return getImBizRecordFieldValueByLabel(item, label);
}
async function handleLinkClick(linkPath: string) {
if (!linkPath || showNoPermission.value) {
return;
}
await navigateImBizRecordLink(linkPath);
}
</script>
<style lang="less" scoped>
.im-biz-record-message {
display: flex;
flex-direction: column;
gap: 12px;
min-width: 280px;
max-width: 420px;
}
.im-biz-record-no-permission {
padding: 12px 10px;
font-size: 13px;
line-height: 1.5;
color: #8c8c8c;
text-align: center;
}
.im-biz-record-peer-tip {
display: inline-flex;
align-items: center;
align-self: flex-start;
margin-top: 4px;
padding: 2px 8px;
border-radius: 10px;
background: #fff7e6;
border: 1px solid #ffd591;
font-size: 12px;
line-height: 1.5;
color: #d46b08;
}
.im-biz-record-item {
display: flex;
flex-direction: column;
gap: 8px;
}
.im-biz-record-table-wrap {
overflow: hidden;
border: 1px solid #f0f0f0;
border-radius: 6px;
background: #fff;
&--list {
overflow-x: auto;
}
}
.im-biz-record-table {
width: 100%;
border-collapse: collapse;
font-size: 13px;
line-height: 1.5;
th,
td {
padding: 8px 10px;
border-bottom: 1px solid #f0f0f0;
vertical-align: top;
word-break: break-word;
}
tr:last-child {
th,
td {
border-bottom: none;
}
}
&--detail {
table-layout: fixed;
th {
width: 38%;
background: #fafafa;
color: #595959;
font-weight: 500;
text-align: left;
}
td {
color: #262626;
background: #fff;
}
}
&--list {
min-width: 100%;
table-layout: auto;
thead th {
background: #fafafa;
color: #595959;
font-weight: 500;
text-align: left;
white-space: nowrap;
}
tbody td {
color: #262626;
background: #fff;
}
}
}
.im-biz-record-link-col {
width: 72px;
min-width: 72px;
white-space: nowrap;
}
.im-biz-record-link {
display: inline-flex;
align-items: center;
gap: 4px;
font-size: 12px;
color: #1677ff;
text-decoration: underline;
cursor: pointer;
&:hover {
color: #0958d9;
}
}
</style>