|
@@ -23,6 +23,45 @@
|
|
|
<span class="duration">{{ msg.duration }}"</span>
|
|
<span class="duration">{{ msg.duration }}"</span>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
+ <!-- 对话样式消息 -->
|
|
|
|
|
+ <div v-if="msg.messageType === 'dialog'" class="dialog-message">
|
|
|
|
|
+ <div class="dialog-title">{{ msg.content.title }}</div>
|
|
|
|
|
+ <div class="dialog-content">{{ msg.content.content }}</div>
|
|
|
|
|
+ <div class="before-after-comparison">
|
|
|
|
|
+ <div class="comparison-item before">
|
|
|
|
|
+ <div class="comparison-label">{{ msg.content.beforeAfter.before.title }}</div>
|
|
|
|
|
+ <div class="comparison-image">
|
|
|
|
|
+ <img :src="msg.content.beforeAfter.before.image" alt="农事前" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="vs-icon">VS</div>
|
|
|
|
|
+ <div class="comparison-item after">
|
|
|
|
|
+ <div class="comparison-label">{{ msg.content.beforeAfter.after.title }}</div>
|
|
|
|
|
+ <div class="comparison-image">
|
|
|
|
|
+ <img :src="msg.content.beforeAfter.after.image" alt="农事后" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="work-details">
|
|
|
|
|
+ <div class="detail-item">
|
|
|
|
|
+ <span class="detail-label">农事名称:</span>
|
|
|
|
|
+ <span class="detail-value">{{ msg.content.workDetails.name }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="detail-item">
|
|
|
|
|
+ <span class="detail-label">所属分类:</span>
|
|
|
|
|
+ <span class="detail-value">{{ msg.content.workDetails.section }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="detail-item">
|
|
|
|
|
+ <span class="detail-label">推荐时间:</span>
|
|
|
|
|
+ <span class="detail-value">{{ msg.content.workDetails.executeDate }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="detail-item">
|
|
|
|
|
+ <span class="detail-label">触发条件:</span>
|
|
|
|
|
+ <span class="detail-value">{{ msg.content.workDetails.condition }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
<!-- <div class="time">{{ msg.time }}</div> -->
|
|
<!-- <div class="time">{{ msg.time }}</div> -->
|
|
|
</div>
|
|
</div>
|
|
|
</template>
|
|
</template>
|
|
@@ -44,6 +83,12 @@
|
|
|
<span class="duration">{{ msg.duration }}"</span>
|
|
<span class="duration">{{ msg.duration }}"</span>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
+ <!-- 对话样式消息 -->
|
|
|
|
|
+ <div v-if="msg.messageType === 'dialog'" class="dialog-message">
|
|
|
|
|
+ <div class="dialog-title">{{ msg.content.title }}</div>
|
|
|
|
|
+ <img src="@/assets/img/monitor/image.png" alt="" class="monitor-image">
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
<!-- <div class="time">{{ msg.time }}</div> -->
|
|
<!-- <div class="time">{{ msg.time }}</div> -->
|
|
|
</div>
|
|
</div>
|
|
|
<!-- <div class="avatar avatar-r">{{ msg.senderName.charAt(0) }}</div> -->
|
|
<!-- <div class="avatar avatar-r">{{ msg.senderName.charAt(0) }}</div> -->
|
|
@@ -51,7 +96,27 @@
|
|
|
</template>
|
|
</template>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 功能按钮区域 -->
|
|
|
|
|
+ <div class="function-buttons">
|
|
|
|
|
+ <el-select v-model="farmVal" size="large">
|
|
|
|
|
+ <el-option
|
|
|
|
|
+ v-for="item in options"
|
|
|
|
|
+ :key="item.id"
|
|
|
|
|
+ :label="item.name"
|
|
|
|
|
+ :value="item.id"
|
|
|
|
|
+ />
|
|
|
|
|
+ </el-select>
|
|
|
|
|
+ <div
|
|
|
|
|
+ v-for="(btn, index) in functionButtons"
|
|
|
|
|
+ :key="index"
|
|
|
|
|
+ class="function-btn"
|
|
|
|
|
+ @click="btn.handler"
|
|
|
|
|
+ >
|
|
|
|
|
+ <span class="btn-text">{{ btn.text }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
<!-- 输入框区域 -->
|
|
<!-- 输入框区域 -->
|
|
|
<div class="input-area">
|
|
<div class="input-area">
|
|
|
<div class="toolbar">
|
|
<div class="toolbar">
|
|
@@ -93,12 +158,14 @@
|
|
|
|
|
|
|
|
<script setup>
|
|
<script setup>
|
|
|
import { ref, onMounted, onUnmounted, nextTick, watch, onActivated, onDeactivated } from "vue";
|
|
import { ref, onMounted, onUnmounted, nextTick, watch, onActivated, onDeactivated } from "vue";
|
|
|
|
|
+import { useRouter } 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";
|
|
|
|
|
|
|
|
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 props = defineProps({
|
|
const props = defineProps({
|
|
|
text:{
|
|
text:{
|
|
@@ -133,6 +200,9 @@ const receiverIdVal = ref(null)
|
|
|
|
|
|
|
|
//聊天会话
|
|
//聊天会话
|
|
|
const createSession = (toUserId,callback) =>{
|
|
const createSession = (toUserId,callback) =>{
|
|
|
|
|
+ // 先保存当前的对话样式消息 要注释
|
|
|
|
|
+ const dialogMessages = messages.value.filter(msg => msg.messageType === 'dialog');
|
|
|
|
|
+
|
|
|
VE_API.bbs.createSession({toUserId}).then((res) => {
|
|
VE_API.bbs.createSession({toUserId}).then((res) => {
|
|
|
senderIcon.value = res.data.senderIcon
|
|
senderIcon.value = res.data.senderIcon
|
|
|
receiverIcon.value = res.data.receiverIcon
|
|
receiverIcon.value = res.data.receiverIcon
|
|
@@ -150,6 +220,12 @@ const createSession = (toUserId,callback) =>{
|
|
|
receiverIcon:res.data.receiverIcon
|
|
receiverIcon:res.data.receiverIcon
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
|
|
+
|
|
|
|
|
+ // 重新添加对话样式消息 要注释
|
|
|
|
|
+ if(dialogMessages.length > 0) {
|
|
|
|
|
+ messages.value = [...messages.value, ...dialogMessages];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
setTimeout(()=>{
|
|
setTimeout(()=>{
|
|
|
scrollToBottom();
|
|
scrollToBottom();
|
|
|
},300)
|
|
},300)
|
|
@@ -215,7 +291,7 @@ const mqttClient = ref(null)
|
|
|
const messagesContainer = ref(null);
|
|
const messagesContainer = ref(null);
|
|
|
|
|
|
|
|
// 消息数据
|
|
// 消息数据
|
|
|
-const messages = ref();
|
|
|
|
|
|
|
+const messages = ref([]);
|
|
|
|
|
|
|
|
// 输入相关
|
|
// 输入相关
|
|
|
const inputMessage = ref("");
|
|
const inputMessage = ref("");
|
|
@@ -264,10 +340,13 @@ const initMqtt = () => {
|
|
|
const sendMessage = (message) => {
|
|
const sendMessage = (message) => {
|
|
|
if(message.messageType === 'text'){
|
|
if(message.messageType === 'text'){
|
|
|
sendMsg('text',message.content)
|
|
sendMsg('text',message.content)
|
|
|
- }else{
|
|
|
|
|
|
|
+ }else if(message.messageType === 'image'){
|
|
|
sendMsg('image','',{
|
|
sendMsg('image','',{
|
|
|
originUrl:message.content
|
|
originUrl:message.content
|
|
|
})
|
|
})
|
|
|
|
|
+ }else if(message.messageType === 'dialog'){
|
|
|
|
|
+ // 对话样式消息不发送到服务器,只显示在本地
|
|
|
|
|
+ console.log('发送对话样式消息:', message.content);
|
|
|
}
|
|
}
|
|
|
messages.value.push(message);
|
|
messages.value.push(message);
|
|
|
scrollToBottom();
|
|
scrollToBottom();
|
|
@@ -408,6 +487,32 @@ const addEmoji = (emoji) => {
|
|
|
showEmojiPicker.value = false;
|
|
showEmojiPicker.value = false;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+// 功能按钮配置
|
|
|
|
|
+const functionButtons = ref([
|
|
|
|
|
+ {
|
|
|
|
|
+ text: '农场报告',
|
|
|
|
|
+ handler: () => {
|
|
|
|
|
+ console.log('点击农场报告,农场ID:', farmVal.value);
|
|
|
|
|
+ // 跳转到农场报告页面
|
|
|
|
|
+ // router.push(`/farm_report?farmId=${farmVal.value}`);
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ text: '农事卡片',
|
|
|
|
|
+ handler: () => {
|
|
|
|
|
+ // 跳转到农事卡片页面
|
|
|
|
|
+ router.push(`/farm_card?farmId=${farmVal.value}`);
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ text: '农场相册',
|
|
|
|
|
+ handler: () => {
|
|
|
|
|
+ // 跳转到农场相册页面
|
|
|
|
|
+ router.push(`/farm_photo`);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+]);
|
|
|
|
|
+
|
|
|
// 辅助函数
|
|
// 辅助函数
|
|
|
const getCurrentTime = () => {
|
|
const getCurrentTime = () => {
|
|
|
return new Date().toLocaleTimeString("zh-CN", {
|
|
return new Date().toLocaleTimeString("zh-CN", {
|
|
@@ -426,16 +531,56 @@ const scrollToBottom = () => {
|
|
|
});
|
|
});
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+const farmVal = ref('')
|
|
|
|
|
+const options = ref([])
|
|
|
|
|
+
|
|
|
|
|
+// 获取农场列表
|
|
|
|
|
+function getFarmList() {
|
|
|
|
|
+ VE_API.farm.userFarmSelectOption().then(({data}) => {
|
|
|
|
|
+ options.value = data || []
|
|
|
|
|
+ if (data && data.length > 0) {
|
|
|
|
|
+ farmVal.value = data[0].id
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// 生命周期钩子
|
|
// 生命周期钩子
|
|
|
onMounted(() => {
|
|
onMounted(() => {
|
|
|
// scrollToBottom();
|
|
// scrollToBottom();
|
|
|
|
|
+ getFarmList();
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
onActivated(()=>{
|
|
onActivated(()=>{
|
|
|
if(props.userId){
|
|
if(props.userId){
|
|
|
scrollToBottom();
|
|
scrollToBottom();
|
|
|
}
|
|
}
|
|
|
|
|
+ // 检查是否有选中的农事工作数据
|
|
|
|
|
+ checkSelectedFarmWork();
|
|
|
})
|
|
})
|
|
|
|
|
+
|
|
|
|
|
+// 检查选中的农事工作数据
|
|
|
|
|
+const checkSelectedFarmWork = () => {
|
|
|
|
|
+ const selectedFarmWork = localStorage.getItem('selectedFarmWork');
|
|
|
|
|
+ if (selectedFarmWork) {
|
|
|
|
|
+ const data = JSON.parse(selectedFarmWork);
|
|
|
|
|
+ // 发送对话样式的消息
|
|
|
|
|
+ sendDialogMessage(data.dialogMessage);
|
|
|
|
|
+ // 清除localStorage中的数据
|
|
|
|
|
+ localStorage.removeItem('selectedFarmWork');
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 发送对话样式的消息
|
|
|
|
|
+const sendDialogMessage = (dialogData) => {
|
|
|
|
|
+ const message = {
|
|
|
|
|
+ sender: "sent",
|
|
|
|
|
+ messageType: "dialog",
|
|
|
|
|
+ senderIcon: senderIcon.value,
|
|
|
|
|
+ content: dialogData,
|
|
|
|
|
+ time: getCurrentTime(),
|
|
|
|
|
+ };
|
|
|
|
|
+ sendMessage(message);
|
|
|
|
|
+}
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
<style scoped lang="scss">
|
|
@@ -465,7 +610,7 @@ onActivated(()=>{
|
|
|
.bubble {
|
|
.bubble {
|
|
|
background-color: white;
|
|
background-color: white;
|
|
|
border-radius: 0 10px 10px 10px;
|
|
border-radius: 0 10px 10px 10px;
|
|
|
- padding: 10px 15px;
|
|
|
|
|
|
|
+ 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);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -651,7 +796,6 @@ onActivated(()=>{
|
|
|
|
|
|
|
|
.emoji-picker span {
|
|
.emoji-picker span {
|
|
|
font-size: 24px;
|
|
font-size: 24px;
|
|
|
- cursor: pointer;
|
|
|
|
|
text-align: center;
|
|
text-align: center;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -659,6 +803,25 @@ onActivated(()=>{
|
|
|
transform: scale(1.2);
|
|
transform: scale(1.2);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/* 功能按钮样式 */
|
|
|
|
|
+.function-buttons {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ gap: 5px;
|
|
|
|
|
+ padding: 5px 10px;
|
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
|
+ .function-btn {
|
|
|
|
|
+ background-color: white;
|
|
|
|
|
+ border-radius: 8px;
|
|
|
|
|
+ padding: 10px 10px;
|
|
|
|
|
+ min-width: 60px;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ .btn-text {
|
|
|
|
|
+ font-size: 14px;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
/* 图片预览 */
|
|
/* 图片预览 */
|
|
|
.image-preview {
|
|
.image-preview {
|
|
|
position: fixed;
|
|
position: fixed;
|
|
@@ -678,4 +841,32 @@ onActivated(()=>{
|
|
|
max-height: 90%;
|
|
max-height: 90%;
|
|
|
object-fit: contain;
|
|
object-fit: contain;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+/* 对话样式消息 */
|
|
|
|
|
+.dialog-message {
|
|
|
|
|
+ max-width: 100%;
|
|
|
|
|
+ background: #fff !important;
|
|
|
|
|
+ padding: 10px;
|
|
|
|
|
+ border-radius: 10px;
|
|
|
|
|
+
|
|
|
|
|
+ .dialog-title {
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ color: rgba(0, 0, 0, 0.6);
|
|
|
|
|
+ margin-bottom: 10px;
|
|
|
|
|
+ }
|
|
|
|
|
+ .monitor-image{
|
|
|
|
|
+ width: 222px;
|
|
|
|
|
+ height: 180px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 我方消息中的对话样式 */
|
|
|
|
|
+.message.sent .dialog-message {
|
|
|
|
|
+ background: #e3f2fd;
|
|
|
|
|
+
|
|
|
|
|
+ .work-details {
|
|
|
|
|
+ background: #f0f8ff;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
</style>
|
|
</style>
|