dongqian 4 weeks ago
parent
commit
ff3ba8b267
  1. 3
      .env.development
  2. 6
      src/api/AIxiaocaishen.js
  3. 76
      src/api/AiEmotionApi.js
  4. BIN
      src/assets/img/AiEmotion/round01.jpg
  5. BIN
      src/assets/img/AiEmotion/round02.jpg
  6. BIN
      src/assets/img/homePage/AI情绪大模型小图标.png
  7. BIN
      src/assets/img/homePage/bk01.jpg
  8. BIN
      src/assets/img/homePage/夺宝奇兵大模型小图标.png
  9. 6
      src/router/index.js
  10. 225
      src/views/AiEmotion.vue
  11. 49
      src/views/homePage.vue

3
.env.development

@ -5,7 +5,8 @@ VITE_OUTPUT_DIR = 'dev'
VITE_PUBLIC_PATH = /
#新数据接口
VITE_APP_API_BASE_URL = "http://39.101.133.168:8828/link"
# VITE_APP_API_BASE_URL = "http://39.101.133.168:8828/link"
VITE_APP_API_BASE_URL = "https://api.homilychart.com/link"
VITE_APP_IMG_API_BASE_URL = "http://39.101.133.168:8828/hljw/api/aws/upload"
#MJ API

6
src/api/AIxiaocaishen.js

@ -141,7 +141,7 @@ export const getReplyAPI = function (params) {
headers: {
"Content-Type": "application/json",
Authorization:
"Bearer pat_DLMr7u1d6pmgC2demIYksrOm0r2k2w9XDxKmHvBvOQ5Lw5AYrByJ2IZpdwoJPYGi",
"Bearer pat_lK1fvhLn9LnWCRETP7yFeR6xQ0niwQdcHJ5ZqpnUk8BdiUWCraPLSzWhiQNp2zOl",
},
});
};
@ -156,7 +156,7 @@ export const getReplyStreamAPI = function (params) {
headers: {
"Content-Type": "application/json",
Authorization:
"Bearer pat_DLMr7u1d6pmgC2demIYksrOm0r2k2w9XDxKmHvBvOQ5Lw5AYrByJ2IZpdwoJPYGi",
"Bearer pat_lK1fvhLn9LnWCRETP7yFeR6xQ0niwQdcHJ5ZqpnUk8BdiUWCraPLSzWhiQNp2zOl",
},
});
};
@ -171,7 +171,7 @@ export const TTSAPI = function (params) {
}),
headers: {
Authorization:
"Bearer pat_DLMr7u1d6pmgC2demIYksrOm0r2k2w9XDxKmHvBvOQ5Lw5AYrByJ2IZpdwoJPYGi",
"Bearer pat_lK1fvhLn9LnWCRETP7yFeR6xQ0niwQdcHJ5ZqpnUk8BdiUWCraPLSzWhiQNp2zOl",
"Content-Type": "application/json",
},
});

76
src/api/AiEmotionApi.js

@ -0,0 +1,76 @@
import request from "../utils/request";
const APIurl = import.meta.env.VITE_APP_API_BASE_URL;
const MJAPIurl = import.meta.env.VITE_APP_MJ_API_BASE_URL;
//数据接口
export const dataListAPI = function (params) {
// URLSearchParams只接受全部字符串的数据
// 将传入数据转化成字符串
const StringParams = new URLSearchParams(
Object.entries(params).map(([key, value]) => [key, String(value)])
);
return request({
url: `${APIurl}/api/brain/data`,
method: "post",
data: StringParams,
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
});
};
// 获取回复接口
export const getReplyAPI = function (params) {
return fetch("https://api.coze.cn/v1/workflow/run", {
method: "POST",
body: JSON.stringify({
workflow_id: "7509384582975897650",
parameters: params,
}),
headers: {
"Content-Type": "application/json",
Authorization:
"Bearer pat_lK1fvhLn9LnWCRETP7yFeR6xQ0niwQdcHJ5ZqpnUk8BdiUWCraPLSzWhiQNp2zOl",
},
});
};
// 获取回复接口流式
export const getReplyStreamAPI = function (params) {
return fetch(`https://api.coze.cn/v1/workflow/stream_run`, {
method: "POST",
body: JSON.stringify({
workflow_id: "7481159261435854860",
parameters: params,
}),
headers: {
"Content-Type": "application/json",
Authorization:
"Bearer pat_lK1fvhLn9LnWCRETP7yFeR6xQ0niwQdcHJ5ZqpnUk8BdiUWCraPLSzWhiQNp2zOl",
},
});
};
// 反馈前台-用户提交反馈接口
export const addFeedbackAPI = function (params) {
return request({
url: `${APIurl}/api/ai_god/feedback/add`,
method: "POST",
data: new URLSearchParams(params),
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
});
};
// 反馈前台-查询该用户提交的全部反馈内容
export const getFeedbackAPI = function (params) {
return request({
url: `${APIurl}/api/ai_god/feedback/select`,
method: "POST",
data: new URLSearchParams(params),
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
});
};

BIN
src/assets/img/AiEmotion/round01.jpg

After

Width: 672  |  Height: 554  |  Size: 22 KiB

BIN
src/assets/img/AiEmotion/round02.jpg

After

Width: 694  |  Height: 550  |  Size: 31 KiB

BIN
src/assets/img/homePage/AI情绪大模型小图标.png

After

Width: 42  |  Height: 42  |  Size: 4.0 KiB

BIN
src/assets/img/homePage/bk01.jpg

After

Width: 750  |  Height: 6060  |  Size: 98 KiB

BIN
src/assets/img/homePage/夺宝奇兵大模型小图标.png

After

Width: 43  |  Height: 42  |  Size: 3.4 KiB

6
src/router/index.js

@ -37,6 +37,11 @@ const routes = [
component: () => import('@/views/Feedback.vue'),
},
{
path: '/AiEmotion',
name: 'AiEmotion',
component: () => import('@/views/AiEmotion.vue')//AI情绪大模型页面
},
{
path: '/DBQBmodel',
name: 'DBQBmodel',
component: () => import('@/views/DBQBmodel.vue'),
@ -46,6 +51,7 @@ const routes = [
name: 'Emotionsmodel',
component: () => import('@/views/Emotionsmodel.vue'),
}
]
// 创建路由实例
const router = createRouter({

225
src/views/AiEmotion.vue

@ -0,0 +1,225 @@
<template>
<div class="ai-emotion-container">
<!-- 居中的图片 -->
<img src="@/assets/img/AiEmotion/round01.jpg" alt="AI情绪图片" class="center-image"
:class="{ rotating: isRotating }" />
<!-- 显示消息内容 -->
<div class="user-input-display">
<div v-for="(message, index) in messages" :key="index" class="message-container">
<!-- 用户输入内容 -->
<div v-if="message.sender === 'user'" class="message-bubble user-message">
{{ message.text }}
</div>
<!-- AI返回结果 -->
<div v-if="message.sender === 'ai'" class="message-bubble ai-message">
<div v-if="message.chartData" id="kline-chart" style="width: 100%; height: 300px;"></div>
<div v-else>
{{ message.response }}
</div>
</div>
</div>
</div>
<!-- 输入框和发送按钮 -->
<div class="input-container fixed-bottom">
<input type="text" v-model="userInput" placeholder="请输入内容..." class="input-box" />
<button @click="sendMessage" class="send-button">发送</button>
</div>
</div>
</template>
<script setup>
import { ref, reactive, nextTick } from 'vue';
import { getReplyAPI } from '@/api/AiEmotionApi.js'; //
import * as echarts from 'echarts'; // ECharts
const userInput = ref('');
const isRotating = ref(false);
const messages = ref([]);
async function sendMessage() {
console.log('发送内容:', userInput.value);
//
isRotating.value = true;
setTimeout(() => {
isRotating.value = false; //
}, 2000); // 2
//
const params = {
content: userInput.value,
userData: {
token: localStorage.getItem('localToken'),
language: 'cn',
brainPrivilegeState: "1",
swordPrivilegeState: "1",
stockForecastPrivile: "1",
spaceForecastPrivile: "1",
aibullPrivilegeState: "1",
aigoldBullPrivilegeS: "1",
airadarPrivilegeStat: "1",
marketList: 'hk,cn,usa,my,sg,vi,in,gb',
},
};
//
try {
const result = await getReplyAPI(params);
const response = await result.json(); // JSON
console.log('工作流接口返回数据:', response);
if (response && response.chartData) {
const aiMessage = reactive({ sender: 'ai', chartData: response.chartData });
messages.value.push(aiMessage);
// K 线
nextTick(() => {
renderKLineChart(response.chartData);
});
} else {
const aiMessage = reactive({ sender: 'ai', response: 'AI思考失败,请稍后再试...' });
messages.value.push(aiMessage);
}
} catch (error) {
console.error('请求失败:', error);
const errorMessage = reactive({ sender: 'ai', response: '请求失败,请稍后重试' });
messages.value.push(errorMessage);
}
}
function renderKLineChart(chartData) {
const chartDom = document.getElementById('kline-chart');
const myChart = echarts.init(chartDom);
const option = {
title: {
text: 'K线图',
left: 'center',
},
tooltip: {
trigger: 'axis',
},
xAxis: {
type: 'category',
data: chartData.dates,
},
yAxis: {
type: 'value',
},
series: [
{
type: 'candlestick',
data: chartData.values,
},
],
};
myChart.setOption(option);
}
</script>
<style scoped>
.ai-emotion-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 20px;
position: relative;
}
.center-image {
max-width: 20%;
/* 缩小为原大小的50% */
height: auto;
margin-bottom: 20px;
border-radius: 100%;
/* 将图片变成圆角 */
transition: transform 2s ease-out;
/* 添加旋转动画 */
}
.center-image.rotating {
transform: rotate(360deg);
/* 旋转360度 */
}
.user-input-display {
margin-top: 20px;
/* 添加与图片的间距 */
display: flex;
flex-direction: column;
width: 100%;
}
.message-container {
display: flex;
margin-bottom: 10px;
}
.user-message {
background-color: #007bff;
color: #fff;
padding: 10px 15px;
border-radius: 15px;
max-width: 60%;
text-align: left;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
align-self: flex-end;
/* 用户消息靠右 */
}
.ai-message {
background-color: #f1f1f1;
color: #333;
padding: 10px 15px;
border-radius: 15px;
max-width: 60%;
text-align: left;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
align-self: flex-start;
/* AI消息靠左 */
}
.input-container {
display: flex;
align-items: center;
gap: 10px;
}
.fixed-bottom {
position: fixed;
bottom: 100px;
/* 向上移动10px */
left: 0;
width: 100%;
background-color: #f8f9fa;
padding: 10px 20px;
box-shadow: 0 -2px 5px rgba(0, 0, 0, 0.1);
}
.input-box {
padding: 10px;
font-size: 16px;
border: 1px solid #ccc;
border-radius: 5px;
width: calc(100% - 120px);
/* 适配按钮宽度 */
}
.send-button {
padding: 10px 20px;
font-size: 16px;
color: #fff;
background-color: #007bff;
border: none;
border-radius: 5px;
cursor: pointer;
}
.send-button:hover {
background-color: #0056b3;
}
</style>

49
src/views/homePage.vue

@ -25,7 +25,7 @@ import voiceNoActive from "../assets/img/homePage/tail/voice-no-active.png";
import sendBtn from "../assets/img/homePage/tail/send.png";
import msgBtn from "../assets/img/homePage/tail/msg.png";
import feedbackBtn from "../assets/img/Feedback/feedbackBtn.png";
import AiEmotion from "./AiEmotion.vue";
// import VConsole from 'vconsole';
@ -51,12 +51,16 @@ const activeIndex = ref(
const tabs = computed(() => [
{
name: "AIchat",
label: "AI对话",
label: "夺宝奇兵大模型",
},
{
name: "AIfind",
label: "发现",
},
{
name: "AiEmotion",
label: "AI情绪大模型"
}
]);
// setActiveTab forceAIchat
@ -84,7 +88,13 @@ const activeComponent = computed(() => {
if (isAnnouncementVisible.value) {
return Announcement;
}
return activeTab.value === "AIchat" ? AIchat : AIfind;
if (activeTab.value === "AIchat") {
return AIchat;
} else if (activeTab.value === "AIfind") {
return AIfind;
} else if (activeTab.value === "AiEmotion") {
return AiEmotion; //
}
});
// AIchat AIchat
@ -486,7 +496,6 @@ onMounted(async () => {
<!-- 主体部分小人 问题轮询图 对话内容 -->
<el-main class="homepage-body">
<div class="main-wrapper">
<section class="tab-section">
<div class="tab-container">
@ -508,9 +517,19 @@ onMounted(async () => {
<!-- 第一行按钮 -->
<div class="footer-first-line">
<div class="left-group">
<img v-if="isThinking" :src="thinkActive" @click="toggleThink" class="action-btn" />
<!-- <img v-if="isThinking" :src="thinkActive" @click="toggleThink" class="action-btn" />
<img v-else :src="thinkNoActive" @click="toggleThink" class="action-btn" />
<img :src="languageBtn" @click="changeLanguage" class="action-btn" />
<img :src="languageBtn" @click="changeLanguage" class="action-btn" /> -->
<div class="action-btn" :class="{ active: activeTab === 'AIchat' }" @click="setActiveTab('AIchat', 0)">
<img src="@/assets/img/homePage/夺宝奇兵大模型小图标.png" alt="夺宝奇兵大模型小图标" class="action-btn-icon" />
<span>夺宝奇兵大模型</span>
</div>
<!-- AI情绪大模型按钮 -->
<div class="action-btn" :class="{ active: activeTab === 'AiEmotion' }"
@click="setActiveTab('AiEmotion', 2)">
<img src="@/assets/img/homePage/AI情绪大模型小图标.png" alt="夺宝奇兵大模型小图标" class="action-btn-icon" />
<span>AI情绪大模型</span>
</div>
<img v-if="isVoice" :src="voice" @click="toggleVoice" class="action-btn" />
<img v-else :src="voiceNoActive" @click="toggleVoice" class="action-btn" />
</div>
@ -577,12 +596,12 @@ onMounted(async () => {
</p>
</div>
<!-- <template #footer> -->
<!-- 添加一个div来包裹按钮并设置样式使其居中 -->
<!-- <div style="text-align: center"> -->
<!-- <el-button style="background-color: orange; color: white; border: none" @click="goToRecharge"> -->
<!-- 去充值 -->
<!-- </el-button> -->
<!-- </div> -->
<!-- 添加一个div来包裹按钮并设置样式使其居中 -->
<!-- <div style="text-align: center"> -->
<!-- <el-button style="background-color: orange; color: white; border: none" @click="goToRecharge"> -->
<!-- 去充值 -->
<!-- </el-button> -->
<!-- </div> -->
<!-- </template> -->
</el-dialog>
</div>
@ -671,7 +690,7 @@ body {
/* height: var(--app-height, 100vh); */
height: var(--app-height, 100vh);
margin: 0 auto;
background-image: url(/src/assets/img/homePage/bk.png);
background-image: url(/src/assets/img/homePage/bk01.jpg);
background-size: 100% 100%;
background-repeat: no-repeat;
background-position: center;
@ -872,6 +891,7 @@ body {
transform: scale(1.05);
}
.send-btn {
margin-left: auto;
margin-right: 5px;
@ -938,8 +958,7 @@ body {
}
}
.ruleContent{
.ruleContent {
text-align: center;
}
</style>
Loading…
Cancel
Save