Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 30 additions & 30 deletions docs/.vuepress/client.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,33 @@
import { defineClientConfig } from '@vuepress/client'
import Container from './components/Container.vue'
import Toc from './components/Toc.vue'
import Link from './components/Link.vue'
import ImageGallery from './components/ImageGallery.vue'
import ImageItem from './components/ImageItem.vue'
import WjxLayout from './layouts/WjxLayout.vue'
import InstanceSearchLayout from './layouts/InstanceSearchLayout.vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import 'instantsearch.css/themes/algolia-min.css'
import InstantSearch from 'vue-instantsearch/vue3/es/index.js'
import BiliBiliPlayer from './components/BiliBili.vue'
import DemoCard from './components/DemoCard.vue'
import FeedBack from './components/Feedback.vue'
import { embedChatbot } from "./embed"
import { defineClientConfig } from "@vuepress/client";
import Container from "./components/Container.vue";
import Toc from "./components/Toc.vue";
import Link from "./components/Link.vue";
import ImageGallery from "./components/ImageGallery.vue";
import ImageItem from "./components/ImageItem.vue";
import WjxLayout from "./layouts/WjxLayout.vue";
import InstanceSearchLayout from "./layouts/InstanceSearchLayout.vue";
import ElementPlus from "element-plus";
import "element-plus/dist/index.css";
import "instantsearch.css/themes/algolia-min.css";
import InstantSearch from "vue-instantsearch/vue3/es/index.js";
import BiliBiliPlayer from "./components/BiliBili.vue";
import ImageHotspot from "./components/ImageHotspot.vue";
import DemoCard from "./components/DemoCard.vue";
import FeedBack from "./components/Feedback.vue";
import { embedChatbot } from "./embed";

export default defineClientConfig({
enhance({ app, router, siteData }) {
app.component('Container', Container)
app.use(ElementPlus)
app.component('Toc', Toc)
app.component('Link', Link)
app.component('ImageGallery', ImageGallery)
app.component('ImageItem', ImageItem)
app.component('BiliBiliPlayer', BiliBiliPlayer)
app.use(InstantSearch)
app.component('DemoCard', DemoCard)
app.component("Container", Container);
app.use(ElementPlus);
app.component("Toc", Toc);
app.component("ImageHotspot", ImageHotspot);
app.component("Link", Link);
app.component("ImageGallery", ImageGallery);
app.component("ImageItem", ImageItem);
app.component("BiliBiliPlayer", BiliBiliPlayer);
app.use(InstantSearch);
app.component("DemoCard", DemoCard);

if (typeof window !== "undefined") {
embedChatbot();
Expand All @@ -34,9 +36,7 @@ export default defineClientConfig({
setup() {},
layouts: {
WjxLayout,
InstanceSearchLayout
InstanceSearchLayout,
},
rootComponents: [
FeedBack
]
})
rootComponents: [FeedBack],
});
104 changes: 104 additions & 0 deletions docs/.vuepress/components/ImageHotspot.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<template>
<div class="image-hotspot-wrapper" :style="{ maxWidth: maxWidth }">
<img :src="src" :alt="alt" loading="lazy" ref="imageEl" @load="onImageLoad">
<a v-for="(spot, i) in computedHotspots" :key="i" :href="spot.link" class="hotspot"
:style="getHotspotStyle(spot)" :aria-label="spot.label">
<span class="hotspot-tooltip">{{ spot.label }}</span>
</a>
</div>
</template>

<script setup>
import { ref, computed } from 'vue'

const props = defineProps({
src: { type: String, required: true },
alt: { type: String, default: '' },
maxWidth: { type: String, default: '800px' },
hotspots: { type: Array, default: () => [] },
designSize: {
type: Object,
default: null, // { width: 406, height: 354 }
description: '设计稿原始尺寸,用于自动转换像素坐标'
}
})

const imageEl = ref(null)
// 智能判断坐标类型并转换
const computedHotspots = computed(() => {
if (!props.hotspots.length) return []

// 检测第一个热点:如果x>1则认为是像素单位
const isPixelBased = props.hotspots[0].x > 1
if (!isPixelBased) return props.hotspots // 已是百分比,直接返回

// 必须有 designSize 才能转换
if (!props.designSize?.width || !props.designSize?.height) {
console.error('❌ 检测到像素坐标但未提供 designSize!')
return props.hotspots
}

return props.hotspots.map(spot => ({
...spot,
x: (spot.x / props.designSize.width) * 100,
y: (spot.y / props.designSize.height) * 100,
w: (spot.w / props.designSize.width) * 100,
h: (spot.h / props.designSize.height) * 100
}))
})

const getHotspotStyle = (spot) => ({
left: `${spot.x}%`,
top: `${spot.y}%`,
width: `${spot.w}%`,
height: `${spot.h}%`
})
</script>


<style scoped>
.image-hotspot-wrapper {
position: relative;
display: inline-block;
margin: 16px 0;
}

.image-hotspot-wrapper img {
width: 100%;
height: auto;
display: block;
}

.hotspot {
position: absolute;
background: rgba(52, 152, 219, 0.08);
transition: all 0.2s ease;
border-radius: 4px;
pointer-events: auto;
}

.hotspot:hover {
background: rgba(52, 152, 219, 0.379);
transform: scale(1.02);
}

.hotspot-tooltip {
position: absolute;
bottom: 100%;
left: 50%;
transform: translateX(-50%);
background: #2c3e50;
color: white;
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
white-space: nowrap;
opacity: 0;
pointer-events: none;
transition: opacity 0.2s;
}

.hotspot:hover .hotspot-tooltip {
opacity: 1;
}
</style>
20 changes: 15 additions & 5 deletions docs/uikit/chatuikit/web/chatuikit_conversationlist_intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,26 @@
<ImageItem src="/images/uikit/chatuikit/web/conversation_list.png" title="会话列表页面" />
</ImageGallery>

<!-- <ImageHotspot
src="/images/uikit/chatuikit/web/conversation_list.png"
alt="会话列表页面"
:designSize="{ width: 406, height: 354 }"
:hotspots="[
{ x: 307, y: 20, w: 71, h: 24, link: '#设置更多会话操作', label: 'AppBar' },
{ x: 307, y: 130, w: 52, h: 24, link: '#自定义会话列表项', label: '按钮' },
]"
/> -->

## 使用示例

```jsx
import React, { useEffect, useState } from 'react';
import { ConversationList } from 'easemob-chat-uikit';
import 'easemob-chat-uikit/style.css';
import React, { useEffect, useState } from "react";
import { ConversationList } from "easemob-chat-uikit";
import "easemob-chat-uikit/style.css";

const Conversation = () => {
return (
<div style={{ width: '30%', height: '100%' }}>
<div style={{ width: "30%", height: "100%" }}>
<ConversationList />
</div>
);
Expand All @@ -38,4 +48,4 @@ const Conversation = () => {

<ImageGallery>
<ImageItem src="/images/uikit/chatuikit/web/cvs-header1.png" title="会话列表页面示例" />
</ImageGallery>
</ImageGallery>
Loading