|
@@ -1,6 +1,6 @@
|
|
|
<template>
|
|
<template>
|
|
|
<div class="consult">
|
|
<div class="consult">
|
|
|
- <custom-header name="咨询专家"></custom-header>
|
|
|
|
|
|
|
+ <custom-header name="咨询专家" @goback="handleBack"></custom-header>
|
|
|
<div class="consult-content">
|
|
<div class="consult-content">
|
|
|
<!-- 聊天消息区域 -->
|
|
<!-- 聊天消息区域 -->
|
|
|
<div class="chat-messages" ref="messagesContainer">
|
|
<div class="chat-messages" ref="messagesContainer">
|
|
@@ -8,48 +8,47 @@
|
|
|
<!-- 对方消息 -->
|
|
<!-- 对方消息 -->
|
|
|
<template v-if="msg.sender === 'received'">
|
|
<template v-if="msg.sender === 'received'">
|
|
|
<!-- <div class="avatar">{{ msg.receiverName.charAt(0) }}</div> -->
|
|
<!-- <div class="avatar">{{ msg.receiverName.charAt(0) }}</div> -->
|
|
|
- <el-avatar
|
|
|
|
|
- class="avatar"
|
|
|
|
|
- :size="40"
|
|
|
|
|
- :src="
|
|
|
|
|
- msg.receiverIcon ||
|
|
|
|
|
- 'https://birdseye-img.sysuimars.com/dinggou-mini/defalut-icon.png'
|
|
|
|
|
- "
|
|
|
|
|
- />
|
|
|
|
|
- <div class="bubble" :class="{ 'no-bubble': msg.messageType === 'image' ,'card-bubble': msg.messageType === 'card'}">
|
|
|
|
|
|
|
+ <el-avatar class="avatar" :size="40" :src="msg.receiverIcon ||
|
|
|
|
|
+ 'https://birdseye-img.sysuimars.com/dinggou-mini/defalut-icon.png'
|
|
|
|
|
+ " />
|
|
|
|
|
+ <div class="bubble"
|
|
|
|
|
+ :class="{ 'no-bubble': msg.messageType === 'image', 'card-bubble': msg.messageType === 'card' }">
|
|
|
<!-- 文本消息 -->
|
|
<!-- 文本消息 -->
|
|
|
<div v-if="msg.messageType === 'text'" class="content">{{ msg.content }}</div>
|
|
<div v-if="msg.messageType === 'text'" class="content">{{ msg.content }}</div>
|
|
|
|
|
|
|
|
<!-- 图片消息 -->
|
|
<!-- 图片消息 -->
|
|
|
<div v-if="msg.messageType === 'image'" class="image-message">
|
|
<div v-if="msg.messageType === 'image'" class="image-message">
|
|
|
- <img
|
|
|
|
|
- :src="msg.content + resize"
|
|
|
|
|
- @click="showImagePreview(msg.content)"
|
|
|
|
|
- @load="handleImageLoad"
|
|
|
|
|
- alt="图片"
|
|
|
|
|
- />
|
|
|
|
|
|
|
+ <img :src="msg.content + resize" @click="showImagePreview(msg.content)"
|
|
|
|
|
+ @load="handleImageLoad" alt="图片" />
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<!-- 对话样式消息 -->
|
|
<!-- 对话样式消息 -->
|
|
|
- <div v-if="msg.messageType === 'report'" class="dialog-message" @click="handleReportClick(msg)">
|
|
|
|
|
|
|
+ <div v-if="msg.messageType === 'report'" class="dialog-message"
|
|
|
|
|
+ @click="handleReportClick(msg)">
|
|
|
<template v-if="(msg.reportType || msg.content.reportType) === 'farm_report'">
|
|
<template v-if="(msg.reportType || msg.content.reportType) === 'farm_report'">
|
|
|
- <div class="report-title">{{ msg.title ||msg.content.title }}</div>
|
|
|
|
|
- <div class="dialog-title">这是{{curRole == 2 ? '该农场' : '我'}}的果园情况,请查看~</div>
|
|
|
|
|
- <img src="https://birdseye-img.sysuimars.com/birdseye-look-mini/share-report-bg.png" alt="" class="monitor-image" />
|
|
|
|
|
|
|
+ <div class="report-title">{{ msg.title || msg.content.title }}</div>
|
|
|
|
|
+ <div class="dialog-title">这是{{ curRole == 2 ? '该农场' : '我' }}的果园情况,请查看~</div>
|
|
|
|
|
+ <img src="https://birdseye-img.sysuimars.com/birdseye-look-mini/share-report-bg.png"
|
|
|
|
|
+ alt="" class="monitor-image" />
|
|
|
</template>
|
|
</template>
|
|
|
<template v-else>
|
|
<template v-else>
|
|
|
- <div class="dialog-title">{{ msg.title || msg.content.title}}</div>
|
|
|
|
|
|
|
+ <div class="dialog-title">{{ msg.title || msg.content.title }}</div>
|
|
|
<img src="@/assets/img/monitor/image.png" alt="" class="monitor-image" />
|
|
<img src="@/assets/img/monitor/image.png" alt="" class="monitor-image" />
|
|
|
</template>
|
|
</template>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
- <!-- 对话样式消息 -->
|
|
|
|
|
- <div v-if="msg.messageType === 'question'" class="question-message" @click="handleCardClick(msg)">
|
|
|
|
|
- <div class="question-title">{{ msg.content }}</div>
|
|
|
|
|
|
|
+ <!-- 对话样式消息 -->
|
|
|
|
|
+ <div v-if="msg.messageType === 'card'" class="question-message">
|
|
|
|
|
+ <div class="question-title">{{ msg.title || msg.content.title }}</div>
|
|
|
<div class="image-wrap">
|
|
<div class="image-wrap">
|
|
|
- <img src="@/assets/img/monitor/image.png" alt="" />
|
|
|
|
|
- <img src="@/assets/img/monitor/image.png" alt="" />
|
|
|
|
|
- <img src="@/assets/img/monitor/image.png" alt="" />
|
|
|
|
|
|
|
+ <!-- coverUrl 为 JSON 字符串的数组时,解析后遍历 -->
|
|
|
|
|
+ <template
|
|
|
|
|
+ v-if="msg.content && msg.content.coverUrl && Array.isArray(msg.content.coverUrl)">
|
|
|
|
|
+ <img v-for="item in msg.content.coverUrl" :key="item" :src="handleImgUrl(item)"
|
|
|
|
|
+ alt="" />
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <!-- 否则当作普通字符串 URL 使用 -->
|
|
|
|
|
+ <img v-else :src="handleImgUrl(msg.content.coverUrl)" alt="">
|
|
|
</div>
|
|
</div>
|
|
|
<div class="btn-detail" @click="handleDetailClick">查看详情</div>
|
|
<div class="btn-detail" @click="handleDetailClick">查看详情</div>
|
|
|
</div>
|
|
</div>
|
|
@@ -58,54 +57,52 @@
|
|
|
|
|
|
|
|
<!-- 我方消息 -->
|
|
<!-- 我方消息 -->
|
|
|
<template v-else>
|
|
<template v-else>
|
|
|
- <div class="bubble" :class="{ 'no-bubble': msg.messageType === 'image','card-bubble': msg.messageType === 'card' || msg.messageType === 'report' }">
|
|
|
|
|
|
|
+ <div class="bubble"
|
|
|
|
|
+ :class="{ 'no-bubble': msg.messageType === 'image', 'card-bubble': msg.messageType === 'card' || msg.messageType === 'report' }">
|
|
|
<!-- 文本消息 -->
|
|
<!-- 文本消息 -->
|
|
|
<div v-if="msg.messageType === 'text'" class="content">{{ msg.content }}</div>
|
|
<div v-if="msg.messageType === 'text'" class="content">{{ msg.content }}</div>
|
|
|
|
|
|
|
|
<!-- 图片消息 -->
|
|
<!-- 图片消息 -->
|
|
|
<div v-if="msg.messageType === 'image'" class="image-message">
|
|
<div v-if="msg.messageType === 'image'" class="image-message">
|
|
|
- <img
|
|
|
|
|
- :src="msg.content + resize"
|
|
|
|
|
- @click="showImagePreview(msg.content)"
|
|
|
|
|
- @load="handleImageLoad"
|
|
|
|
|
- alt="图片"
|
|
|
|
|
- />
|
|
|
|
|
|
|
+ <img :src="msg.content + resize" @click="showImagePreview(msg.content)"
|
|
|
|
|
+ @load="handleImageLoad" alt="图片" />
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<!-- 对话样式消息 -->
|
|
<!-- 对话样式消息 -->
|
|
|
- <div v-if="msg.messageType === 'report'" class="dialog-message" @click="handleReportClick(msg)">
|
|
|
|
|
|
|
+ <div v-if="msg.messageType === 'report'" class="dialog-message"
|
|
|
|
|
+ @click="handleReportClick(msg)">
|
|
|
<template v-if="(msg.reportType || msg.content.reportType) === 'farm_report'">
|
|
<template v-if="(msg.reportType || msg.content.reportType) === 'farm_report'">
|
|
|
- <div class="report-title">{{ msg.title ||msg.content.title }}</div>
|
|
|
|
|
- <div class="dialog-title">这是{{curRole == 2 ? '该农场' : '我'}}果园情况,请查看~</div>
|
|
|
|
|
- <img src="https://birdseye-img.sysuimars.com/birdseye-look-mini/share-report-bg.png" alt="" class="monitor-image" />
|
|
|
|
|
|
|
+ <div class="report-title">{{ msg.title || msg.content.title }}</div>
|
|
|
|
|
+ <div class="dialog-title">这是{{ curRole == 2 ? '该农场' : '我' }}果园情况,请查看~</div>
|
|
|
|
|
+ <img src="https://birdseye-img.sysuimars.com/birdseye-look-mini/share-report-bg.png"
|
|
|
|
|
+ alt="" class="monitor-image" />
|
|
|
</template>
|
|
</template>
|
|
|
<template v-else>
|
|
<template v-else>
|
|
|
- <div class="dialog-title">{{ msg.title || msg.content.title}}</div>
|
|
|
|
|
|
|
+ <div class="dialog-title">{{ msg.title || msg.content.title }}</div>
|
|
|
<img src="@/assets/img/monitor/image.png" alt="" class="monitor-image" />
|
|
<img src="@/assets/img/monitor/image.png" alt="" class="monitor-image" />
|
|
|
</template>
|
|
</template>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<!-- 对话样式消息 -->
|
|
<!-- 对话样式消息 -->
|
|
|
- <div v-if="msg.messageType === 'card'" class="card-message" @click="handleCardClick(msg)">
|
|
|
|
|
- <template v-if="(msg.cardType || msg.content.cardType) === 'quotation'">
|
|
|
|
|
- <div class="card-title">向您发送了一张 服务报价单</div>
|
|
|
|
|
- <img src="https://birdseye-img.sysuimars.com/temp/price.png" alt="" />
|
|
|
|
|
- </template>
|
|
|
|
|
- <template v-else>
|
|
|
|
|
- <div class="card-title">{{ msg.title || msg.content.title }}</div>
|
|
|
|
|
- <img :src="handleImgUrl(msg.coverUrl || msg.content.coverUrl)" alt="" />
|
|
|
|
|
- </template>
|
|
|
|
|
|
|
+ <div v-if="msg.messageType === 'card'" class="question-message">
|
|
|
|
|
+ <div class="question-title">{{ msg.title || msg.content.title }}</div>
|
|
|
|
|
+ <div class="image-wrap">
|
|
|
|
|
+ <!-- coverUrl 为 JSON 字符串的数组时,解析后遍历 -->
|
|
|
|
|
+ <template
|
|
|
|
|
+ v-if="msg.content && msg.content.coverUrl && Array.isArray(msg.content.coverUrl)">
|
|
|
|
|
+ <img v-for="item in msg.content.coverUrl" :key="item" :src="handleImgUrl(item)"
|
|
|
|
|
+ alt="" />
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <!-- 否则当作普通字符串 URL 使用 -->
|
|
|
|
|
+ <img v-else :src="handleImgUrl(msg.content.coverUrl)" alt="">
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="btn-detail" @click="handleDetailClick">查看详情</div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
<!-- <div class="avatar avatar-r">{{ msg.senderName.charAt(0) }}</div> -->
|
|
<!-- <div class="avatar avatar-r">{{ msg.senderName.charAt(0) }}</div> -->
|
|
|
- <el-avatar
|
|
|
|
|
- class="avatar avatar-r"
|
|
|
|
|
- :size="40"
|
|
|
|
|
- :src="
|
|
|
|
|
- msg.senderIcon ||
|
|
|
|
|
- 'https://birdseye-img.sysuimars.com/dinggou-mini/defalut-icon.png'
|
|
|
|
|
- "
|
|
|
|
|
- />
|
|
|
|
|
|
|
+ <el-avatar class="avatar avatar-r" :size="40" :src="msg.senderIcon ||
|
|
|
|
|
+ 'https://birdseye-img.sysuimars.com/dinggou-mini/defalut-icon.png'
|
|
|
|
|
+ " />
|
|
|
</template>
|
|
</template>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
@@ -117,7 +114,7 @@
|
|
|
<input type="file" ref="fileInput" accept="image/*" style="display: none" @change="handleImageUpload" />
|
|
<input type="file" ref="fileInput" accept="image/*" style="display: none" @change="handleImageUpload" />
|
|
|
</div> -->
|
|
</div> -->
|
|
|
|
|
|
|
|
- <input type="text" v-model="inputMessage" placeholder="给 专家 发送消息" @keyup.enter="sendTextMessage" />
|
|
|
|
|
|
|
+ <input type="text" v-model="inputMessage" placeholder="请输入你想说的话~" @keyup.enter="sendTextMessage" />
|
|
|
<div class="send" @click="sendTextMessage">发送</div>
|
|
<div class="send" @click="sendTextMessage">发送</div>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
@@ -131,36 +128,23 @@
|
|
|
|
|
|
|
|
<script setup>
|
|
<script setup>
|
|
|
import { ref, nextTick, onDeactivated, onMounted } from "vue";
|
|
import { ref, nextTick, onDeactivated, onMounted } from "vue";
|
|
|
-import { useRouter ,useRoute} from "vue-router";
|
|
|
|
|
|
|
+import { useRouter, useRoute } from "vue-router";
|
|
|
import { base_img_url2 } from "@/api/config";
|
|
import { base_img_url2 } from "@/api/config";
|
|
|
import { getFileExt } from "@/utils/util";
|
|
import { getFileExt } from "@/utils/util";
|
|
|
import UploadFile from "@/utils/upliadFile";
|
|
import UploadFile from "@/utils/upliadFile";
|
|
|
import MqttClient from "@/plugins/MqttClient";
|
|
import MqttClient from "@/plugins/MqttClient";
|
|
|
import customHeader from "@/components/customHeader.vue";
|
|
import customHeader from "@/components/customHeader.vue";
|
|
|
-
|
|
|
|
|
|
|
+import { useStore } from "vuex";
|
|
|
|
|
+const store = useStore();
|
|
|
const resize = "?x-oss-process=image/resize,p_120/format,webp/quality,q_100";
|
|
const resize = "?x-oss-process=image/resize,p_120/format,webp/quality,q_100";
|
|
|
const router = useRouter();
|
|
const router = useRouter();
|
|
|
const route = useRoute();
|
|
const route = useRoute();
|
|
|
|
|
|
|
|
-const props = defineProps({
|
|
|
|
|
- text: {
|
|
|
|
|
- type: String,
|
|
|
|
|
- defalut: "",
|
|
|
|
|
- },
|
|
|
|
|
- img: {
|
|
|
|
|
- type: String,
|
|
|
|
|
- defalut: "",
|
|
|
|
|
- },
|
|
|
|
|
- userId: {
|
|
|
|
|
- type: [String, Number],
|
|
|
|
|
- defalut: "",
|
|
|
|
|
- },
|
|
|
|
|
-});
|
|
|
|
|
|
|
|
|
|
const curUserId = Number(localStorage.getItem("MINI_USER_ID"));
|
|
const curUserId = Number(localStorage.getItem("MINI_USER_ID"));
|
|
|
|
|
+const storeFarmId = ref(store.state.home.gardenId)
|
|
|
const senderIcon = ref("");
|
|
const senderIcon = ref("");
|
|
|
const receiverIcon = ref("");
|
|
const receiverIcon = ref("");
|
|
|
-const receiverIdVal = ref(null);
|
|
|
|
|
|
|
|
|
|
// 本地用户头像
|
|
// 本地用户头像
|
|
|
const localUserInfoIcon = (() => {
|
|
const localUserInfoIcon = (() => {
|
|
@@ -172,13 +156,56 @@ const localUserInfoIcon = (() => {
|
|
|
}
|
|
}
|
|
|
})();
|
|
})();
|
|
|
|
|
|
|
|
-// 初始化本地头像为默认发送者头像
|
|
|
|
|
-senderIcon.value = localUserInfoIcon;
|
|
|
|
|
-
|
|
|
|
|
// mqtt 连接
|
|
// mqtt 连接
|
|
|
const mqttClient = ref(null);
|
|
const mqttClient = ref(null);
|
|
|
const messagesContainer = ref(null);
|
|
const messagesContainer = ref(null);
|
|
|
|
|
|
|
|
|
|
+// 初始化 mqtt
|
|
|
|
|
+const initMqtt = () => {
|
|
|
|
|
+ const topics = [`user/chat/message/${storeFarmId.value}/${curUserId}`]; // 订阅的主题数组
|
|
|
|
|
+ mqttClient.value = new MqttClient(topics, (topic, message) => {
|
|
|
|
|
+ if (message && message.length > 10) {
|
|
|
|
|
+ const obj = JSON.parse(message);
|
|
|
|
|
+ console.log("message有值", obj);
|
|
|
|
|
+ if (obj.senderId === curUserId) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (obj.senderId === Number(route.query.userId)) {
|
|
|
|
|
+ // 检查是否已存在相同 id 的消息,避免重复添加
|
|
|
|
|
+ if (obj.id && messages.value.some(msg => msg.id === obj.id)) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (obj.messageType === "image") {
|
|
|
|
|
+ if (obj.image && (obj.image.url || obj.image.originUrl)) {
|
|
|
|
|
+ obj.content = obj.image.url || obj.image.originUrl;
|
|
|
|
|
+ } else if (obj.content) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const img = JSON.parse(obj.content);
|
|
|
|
|
+ obj.content = img.url || img.originUrl;
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ console.error(e, "e");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ } else if (obj.messageType !== 'text') {
|
|
|
|
|
+ obj.content = JSON.parse(obj.content);
|
|
|
|
|
+ // card 类型的 content 中,如果 coverUrl 是数组,则转成字符串(兼容旧格式)
|
|
|
|
|
+ if (obj.messageType === 'card' && obj.content && Array.isArray(obj.content.coverUrl)) {
|
|
|
|
|
+ obj.content.coverUrl = JSON.stringify(obj.content.coverUrl);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ obj.receiverId = curUserId;
|
|
|
|
|
+ (obj.sender = obj.senderId === curUserId ? "sent" : "received"), (obj.senderIcon = senderIcon.value);
|
|
|
|
|
+ obj.receiverIcon = receiverIcon.value;
|
|
|
|
|
+ messages.value.push(obj);
|
|
|
|
|
+
|
|
|
|
|
+ scrollToBottom();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ mqttClient.value.connect();
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
// 消息数据
|
|
// 消息数据
|
|
|
const messages = ref([]);
|
|
const messages = ref([]);
|
|
|
|
|
|
|
@@ -191,14 +218,12 @@ function handleImageLoad() {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const handleDetailClick = () => {
|
|
const handleDetailClick = () => {
|
|
|
- router.push('/interaction_list');
|
|
|
|
|
|
|
+ router.push(`/interaction_list?expertMiniUserId=${route.query.userId}`);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 图片预览
|
|
// 图片预览
|
|
|
const previewImage = ref(null);
|
|
const previewImage = ref(null);
|
|
|
|
|
|
|
|
-const userId = ref(null);
|
|
|
|
|
-
|
|
|
|
|
const handleCardClick = (msg) => {
|
|
const handleCardClick = (msg) => {
|
|
|
router.push(msg.linkUrl || msg.content.linkUrl);
|
|
router.push(msg.linkUrl || msg.content.linkUrl);
|
|
|
}
|
|
}
|
|
@@ -252,11 +277,10 @@ const sendImageMessage = (thumbnailUrl) => {
|
|
|
//类型 text ,file,image
|
|
//类型 text ,file,image
|
|
|
const sendMsg = (messageType = "text", content = "", obj = {}) => {
|
|
const sendMsg = (messageType = "text", content = "", obj = {}) => {
|
|
|
const params = {
|
|
const params = {
|
|
|
- farmId: farmVal.value,
|
|
|
|
|
- senderId: curUserId,
|
|
|
|
|
- receiverId: userId.value,
|
|
|
|
|
|
|
+ farmId: storeFarmId.value,
|
|
|
|
|
+ receiverId: route.query.userId,
|
|
|
content,
|
|
content,
|
|
|
- [messageType]:obj,
|
|
|
|
|
|
|
+ [messageType]: obj,
|
|
|
messageType,
|
|
messageType,
|
|
|
};
|
|
};
|
|
|
VE_API.bbs.sendMsg(params);
|
|
VE_API.bbs.sendMsg(params);
|
|
@@ -272,22 +296,22 @@ const sendMessage = (message) => {
|
|
|
} else if (message.messageType === "report") {
|
|
} else if (message.messageType === "report") {
|
|
|
// 对话样式消息不发送到服务器,只显示在本地
|
|
// 对话样式消息不发送到服务器,只显示在本地
|
|
|
console.log("发送对话样式消息:", message);
|
|
console.log("发送对话样式消息:", message);
|
|
|
- if(message.reportType === 'farm_report'){
|
|
|
|
|
- sendMsg('report','',{
|
|
|
|
|
|
|
+ if (message.reportType === 'farm_report') {
|
|
|
|
|
+ sendMsg('report', '', {
|
|
|
title: message.title,
|
|
title: message.title,
|
|
|
reportId: message.reportId,
|
|
reportId: message.reportId,
|
|
|
reportType: message.reportType,
|
|
reportType: message.reportType,
|
|
|
});
|
|
});
|
|
|
- }else{
|
|
|
|
|
- sendMsg('report','',{
|
|
|
|
|
|
|
+ } else {
|
|
|
|
|
+ sendMsg('report', '', {
|
|
|
title: message.title,
|
|
title: message.title,
|
|
|
reportId: message.reportId,
|
|
reportId: message.reportId,
|
|
|
reportType: message.reportType,
|
|
reportType: message.reportType,
|
|
|
});
|
|
});
|
|
|
console.log('其他文件1');
|
|
console.log('其他文件1');
|
|
|
}
|
|
}
|
|
|
- }else{
|
|
|
|
|
- sendMsg('card','',{
|
|
|
|
|
|
|
+ } else {
|
|
|
|
|
+ sendMsg('card', '', {
|
|
|
title: message.title,
|
|
title: message.title,
|
|
|
coverUrl: message.coverUrl,
|
|
coverUrl: message.coverUrl,
|
|
|
cardType: message.cardType,
|
|
cardType: message.cardType,
|
|
@@ -322,40 +346,75 @@ const scrollToBottom = () => {
|
|
|
});
|
|
});
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-const farmVal = ref("");
|
|
|
|
|
const curRole = ref(null);
|
|
const curRole = ref(null);
|
|
|
|
|
|
|
|
// 点击农场报告对话框
|
|
// 点击农场报告对话框
|
|
|
const handleReportClick = (msg) => {
|
|
const handleReportClick = (msg) => {
|
|
|
- if(msg.reportType === 'farm_report' || msg.messageType === 'report'){
|
|
|
|
|
|
|
+ if (msg.reportType === 'farm_report' || msg.messageType === 'report') {
|
|
|
const params = {
|
|
const params = {
|
|
|
farmId: msg.reportId || msg.content?.reportId,
|
|
farmId: msg.reportId || msg.content?.reportId,
|
|
|
showFilter: true,
|
|
showFilter: true,
|
|
|
}
|
|
}
|
|
|
router.push(`/farm_report?miniJson=${JSON.stringify(params)}`);
|
|
router.push(`/farm_report?miniJson=${JSON.stringify(params)}`);
|
|
|
- }else{
|
|
|
|
|
|
|
+ } else {
|
|
|
console.log('其他文件');
|
|
console.log('其他文件');
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+const handleBack = () => {
|
|
|
|
|
+ // router.go(-1);
|
|
|
|
|
+ router.replace(`/home`);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// 页面加载时自动添加欢迎消息
|
|
// 页面加载时自动添加欢迎消息
|
|
|
onMounted(() => {
|
|
onMounted(() => {
|
|
|
- const welcomeMessage = {
|
|
|
|
|
- sender: "received",
|
|
|
|
|
- messageType: "text",
|
|
|
|
|
- content: "您好,我叫冼继东。我是种植专家,介绍专家介绍专家",
|
|
|
|
|
- receiverIcon: receiverIcon.value || 'https://birdseye-img.sysuimars.com/dinggou-mini/defalut-icon.png',
|
|
|
|
|
- };
|
|
|
|
|
- const questionMessage = {
|
|
|
|
|
- sender: "received",
|
|
|
|
|
- messageType: "question",
|
|
|
|
|
- content: "为了更方便分析农场问题,请先采集农情互动信息",
|
|
|
|
|
- receiverIcon: receiverIcon.value || 'https://birdseye-img.sysuimars.com/dinggou-mini/defalut-icon.png',
|
|
|
|
|
- };
|
|
|
|
|
- messages.value.push(welcomeMessage,questionMessage);
|
|
|
|
|
|
|
+ createSession(route.query.userId);
|
|
|
scrollToBottom();
|
|
scrollToBottom();
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
|
|
+//聊天会话
|
|
|
|
|
+const createSession = (targetUserId, callback) => {
|
|
|
|
|
+ VE_API.bbs.createSession({ farmId: storeFarmId.value, targetUserId }).then(({ data, code }) => {
|
|
|
|
|
+ if (code === 0) {
|
|
|
|
|
+ senderIcon.value = localUserInfoIcon;
|
|
|
|
|
+ receiverIcon.value = data.session.targetUserAvatar;
|
|
|
|
|
+ messages.value = data.messages.map((item) => {
|
|
|
|
|
+ let content = item.content;
|
|
|
|
|
+ if (item.messageType === "image") {
|
|
|
|
|
+ // 优先读取后端的 image 字段,其次兼容旧的 content(JSON)
|
|
|
|
|
+ if (item.image && (item.image.url || item.image.originUrl)) {
|
|
|
|
|
+ content = item.image.url || item.image.originUrl;
|
|
|
|
|
+ } else if (item.content) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const imgObj = JSON.parse(item.content);
|
|
|
|
|
+ content = imgObj.url || imgObj.originUrl;
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ console.error(e, "e");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ } else if (item.messageType !== 'text') {
|
|
|
|
|
+ content = JSON.parse(item.content);
|
|
|
|
|
+ }
|
|
|
|
|
+ return {
|
|
|
|
|
+ ...item,
|
|
|
|
|
+ content,
|
|
|
|
|
+ sender: item.senderId === curUserId ? "sent" : "received",
|
|
|
|
|
+ senderIcon: item.senderId === curUserId ? localUserInfoIcon : data.session.targetUserAvatar,
|
|
|
|
|
+ receiverIcon: data.session.targetUserAvatar,
|
|
|
|
|
+ };
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ scrollToBottom();
|
|
|
|
|
+ }, 300);
|
|
|
|
|
+ callback && callback();
|
|
|
|
|
+
|
|
|
|
|
+ // 初始化mqtt
|
|
|
|
|
+ initMqtt();
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
onDeactivated(() => {
|
|
onDeactivated(() => {
|
|
|
mqttClient.value && mqttClient.value.client.end(true);
|
|
mqttClient.value && mqttClient.value.client.end(true);
|
|
|
});
|
|
});
|
|
@@ -366,6 +425,7 @@ onDeactivated(() => {
|
|
|
width: 100%;
|
|
width: 100%;
|
|
|
height: calc(100vh - 40px);
|
|
height: calc(100vh - 40px);
|
|
|
box-sizing: border-box;
|
|
box-sizing: border-box;
|
|
|
|
|
+
|
|
|
.consult-content {
|
|
.consult-content {
|
|
|
width: 100%;
|
|
width: 100%;
|
|
|
height: 100%;
|
|
height: 100%;
|
|
@@ -382,29 +442,44 @@ onDeactivated(() => {
|
|
|
overflow-y: auto;
|
|
overflow-y: auto;
|
|
|
background-color: #fff;
|
|
background-color: #fff;
|
|
|
box-sizing: border-box;
|
|
box-sizing: border-box;
|
|
|
|
|
+
|
|
|
.message {
|
|
.message {
|
|
|
display: flex;
|
|
display: flex;
|
|
|
margin-bottom: 15px;
|
|
margin-bottom: 15px;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
.received {
|
|
.received {
|
|
|
justify-content: flex-start;
|
|
justify-content: flex-start;
|
|
|
|
|
+
|
|
|
.bubble {
|
|
.bubble {
|
|
|
background-color: #F4F5F8;
|
|
background-color: #F4F5F8;
|
|
|
border-radius: 0 10px 10px 10px;
|
|
border-radius: 0 10px 10px 10px;
|
|
|
padding: 10px 12px;
|
|
padding: 10px 12px;
|
|
|
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
|
|
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
|
|
|
|
|
+
|
|
|
|
|
+ .content {
|
|
|
|
|
+ font-size: 16px;
|
|
|
|
|
+ color: #666666;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
.sent {
|
|
.sent {
|
|
|
justify-content: flex-end;
|
|
justify-content: flex-end;
|
|
|
|
|
+
|
|
|
.bubble {
|
|
.bubble {
|
|
|
background-color: #07c160;
|
|
background-color: #07c160;
|
|
|
border-radius: 10px 0 10px 10px;
|
|
border-radius: 10px 0 10px 10px;
|
|
|
padding: 10px 15px;
|
|
padding: 10px 15px;
|
|
|
- color: #fff;
|
|
|
|
|
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
|
|
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
|
|
|
|
|
+
|
|
|
|
|
+ .content {
|
|
|
|
|
+ font-size: 16px;
|
|
|
|
|
+ color: #000;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
.avatar {
|
|
.avatar {
|
|
|
width: 40px;
|
|
width: 40px;
|
|
|
height: 40px;
|
|
height: 40px;
|
|
@@ -421,15 +496,13 @@ onDeactivated(() => {
|
|
|
.avatar-r {
|
|
.avatar-r {
|
|
|
margin: 0 0 0 10px;
|
|
margin: 0 0 0 10px;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
.bubble {
|
|
.bubble {
|
|
|
max-width: 70%;
|
|
max-width: 70%;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-.content {
|
|
|
|
|
- font-size: 16px;
|
|
|
|
|
- color: #666666;
|
|
|
|
|
-}
|
|
|
|
|
|
|
+
|
|
|
|
|
|
|
|
.input-area {
|
|
.input-area {
|
|
|
display: flex;
|
|
display: flex;
|
|
@@ -440,6 +513,7 @@ onDeactivated(() => {
|
|
|
position: relative;
|
|
position: relative;
|
|
|
width: 100%;
|
|
width: 100%;
|
|
|
box-sizing: border-box;
|
|
box-sizing: border-box;
|
|
|
|
|
+
|
|
|
input {
|
|
input {
|
|
|
flex: 1;
|
|
flex: 1;
|
|
|
padding: 10px;
|
|
padding: 10px;
|
|
@@ -447,6 +521,7 @@ onDeactivated(() => {
|
|
|
border-radius: 20px;
|
|
border-radius: 20px;
|
|
|
outline: none;
|
|
outline: none;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
.send {
|
|
.send {
|
|
|
margin-left: 10px;
|
|
margin-left: 10px;
|
|
|
padding: 8px 20px;
|
|
padding: 8px 20px;
|
|
@@ -464,7 +539,6 @@ onDeactivated(() => {
|
|
|
max-width: 200px;
|
|
max-width: 200px;
|
|
|
max-height: 200px;
|
|
max-height: 200px;
|
|
|
border-radius: 8px;
|
|
border-radius: 8px;
|
|
|
- cursor: pointer;
|
|
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -476,14 +550,12 @@ onDeactivated(() => {
|
|
|
box-shadow: none !important;
|
|
box-shadow: none !important;
|
|
|
color: inherit !important;
|
|
color: inherit !important;
|
|
|
}
|
|
}
|
|
|
-.card-bubble{
|
|
|
|
|
- background: #fff !important;
|
|
|
|
|
-}
|
|
|
|
|
|
|
|
|
|
/* 工具栏样式 */
|
|
/* 工具栏样式 */
|
|
|
.toolbar {
|
|
.toolbar {
|
|
|
display: flex;
|
|
display: flex;
|
|
|
align-items: center;
|
|
align-items: center;
|
|
|
|
|
+
|
|
|
button {
|
|
button {
|
|
|
background: none;
|
|
background: none;
|
|
|
border: none;
|
|
border: none;
|
|
@@ -492,6 +564,7 @@ onDeactivated(() => {
|
|
|
cursor: pointer;
|
|
cursor: pointer;
|
|
|
padding: 5px;
|
|
padding: 5px;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
.link {
|
|
.link {
|
|
|
font-size: 24px;
|
|
font-size: 24px;
|
|
|
margin-right: 10px;
|
|
margin-right: 10px;
|
|
@@ -523,6 +596,7 @@ onDeactivated(() => {
|
|
|
max-width: 100%;
|
|
max-width: 100%;
|
|
|
background: #fff !important;
|
|
background: #fff !important;
|
|
|
border-radius: 10px;
|
|
border-radius: 10px;
|
|
|
|
|
+
|
|
|
.report-title {
|
|
.report-title {
|
|
|
font-size: 16px;
|
|
font-size: 16px;
|
|
|
font-weight: 600;
|
|
font-weight: 600;
|
|
@@ -535,6 +609,7 @@ onDeactivated(() => {
|
|
|
color: rgba(0, 0, 0, 0.6);
|
|
color: rgba(0, 0, 0, 0.6);
|
|
|
margin-bottom: 10px;
|
|
margin-bottom: 10px;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
.monitor-image {
|
|
.monitor-image {
|
|
|
width: 222px;
|
|
width: 222px;
|
|
|
height: 180px;
|
|
height: 180px;
|
|
@@ -543,6 +618,7 @@ onDeactivated(() => {
|
|
|
|
|
|
|
|
.farm-report-content,
|
|
.farm-report-content,
|
|
|
.farm-work-content {
|
|
.farm-work-content {
|
|
|
|
|
+
|
|
|
.report-details,
|
|
.report-details,
|
|
|
.work-details {
|
|
.work-details {
|
|
|
background: #f8f9fa;
|
|
background: #f8f9fa;
|
|
@@ -573,25 +649,27 @@ onDeactivated(() => {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-.question-message{
|
|
|
|
|
- .question-title{
|
|
|
|
|
|
|
+.question-message {
|
|
|
|
|
+ .question-title {
|
|
|
font-size: 16px;
|
|
font-size: 16px;
|
|
|
color: #666666;
|
|
color: #666666;
|
|
|
margin-bottom: 6px;
|
|
margin-bottom: 6px;
|
|
|
}
|
|
}
|
|
|
- .image-wrap{
|
|
|
|
|
|
|
+
|
|
|
|
|
+ .image-wrap {
|
|
|
display: flex;
|
|
display: flex;
|
|
|
// flex-wrap: wrap;
|
|
// flex-wrap: wrap;
|
|
|
gap: 10px;
|
|
gap: 10px;
|
|
|
- img{
|
|
|
|
|
- flex: 1;
|
|
|
|
|
|
|
+
|
|
|
|
|
+ img {
|
|
|
width: 75px;
|
|
width: 75px;
|
|
|
height: 70px;
|
|
height: 70px;
|
|
|
border-radius: 8px;
|
|
border-radius: 8px;
|
|
|
object-fit: cover;
|
|
object-fit: cover;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- .btn-detail{
|
|
|
|
|
|
|
+
|
|
|
|
|
+ .btn-detail {
|
|
|
font-size: 14px;
|
|
font-size: 14px;
|
|
|
margin-top: 8px;
|
|
margin-top: 8px;
|
|
|
background: #FFFFFF;
|
|
background: #FFFFFF;
|